C/C++|物联网开发入门+项目实战|嵌入式C语言高级|简介及GCC参数|define|编译过程-学习笔记(7)

课程介绍

参考:麦子学院-嵌入式C语言高级

本套课程的定位

前导课程:掌握简单C语言的基本语法
计算机程序语言的学习思路?
基本程序设计思想+语言工具的特性
基本程序设计思想:
数据类型、运算符、条件分支、循环设计
面向对象的设计
C语言工具的特性:
比如操作底层,尤其是内存地址的寻址及操作,指针的使用
掌掘C语言的设计思路,比普通的语法要重要的多
万变不离其宗,掌掘C语言的核心规律。

本套读程的想法

不是教程,是一种嵌入式C语言思想和设计的交流
什么时候用?
怎么用?
为什么要这样设计?

推荐教程

C语言深度解剖(第2版》 解开程序员面试笔试的秘密
C专家编程
程序员面试宝典《第4版)
C和指针

偏重嵌入式方向的使用

嵌入式课程的特点

2-1 : GCC的使用及其常用选项介绍【重点】

掌握C语言如何变成机器指令的过程
gcc工具的几个常用选项的意义
【难点】
C编译过程中在gcc工具上的体现
【实验考核】
自己编写程序,利用gcc工具集验证每一步的执行效果
举例说明gcc选项的意义:
gcc -I gcc -L
gcc -E gcc -S gcc -c

Gcc概述

c语言的编译过程
可参考:C/C++|物联网开发入门+项目实战|C语言基础|C语言的预处理及编译过程分析-学习笔记(2)

C语言常见错误举例

预处理错误;

include “name” 当前目录
include 系统库(环境变量)

not find

示例
从abc1.h中引入字符char_c

#include <stdio.h>
#include "abc1.h"

int main()
{
    char  c=char_c;
    printf("c(char)=%c,c(int)=%d,c_change(char)=%c,c_change(int)=%d,c_change(HEX)=%#x\n",c,c,c+32,c+32,c+0x20);
    return 0;
}

输出:
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
2.c:2:18: fatal error: abc1.h: No such file or directory
compilation terminated.
显然无此文件(文件名错误),改为include “abc.h”,运行正常。
而一般地,将头文件一般放在inc目录下。
建立inc,并把abc.h移入inc:
在这里插入图片描述

1、方法1:修改inclue为#include “./inc/abc.h”;
2、方法2:gcc -I ./inc 2.c -o 2

编译错误

语法错误,

链接错误

打包出错,原材料不够 undefined reference

寻找标签是否实现了,链接时是否加入一起链接
示例

#include <stdio.h>
#include "abc.h"

void fun(void);
int main()
{
    char  c=char_c;
    printf("c(char)=%c,c(int)=%d,c_change(char)=%c,c_change(int)=%d,c_change(HEX)=%#x\n",c,c,c+32,c+32,c+0x20);

    fun();
    return 0;
}

main函数中引用了一个fun函数,但没有fun函数的实现,故链接器collect2.exe时出错,

提示:
E:\temp>gcc -I ./inc 2.c -o 2 && "e:\temp"2
C:\Users\Vera\AppData\Local\Temp\ccRNGpif.o:2.c:(.text+0x4b): undefined reference to `fun’
collect2.exe: error: ld returned 1 exit status
解决方法1:不声明,删除fun()的定义并直接实现一个空函数:

void fun(void)
{

}

方法2:2.c不变,新建立abc.c存放fun()的函数实现,如:
abc.c

void fun(void)
{

}

执行程序:>gcc -I ./inc -o 2 2.c abc.c #将所有用到的原材料放在输出文件之后
方法3:分别编译再拼接

E:\temp>gcc -c -I./inc -o a.o 2.c
E:\temp>gcc -c  -o b.o abc.c

分别编译完成后的文件都输出在当前目录下:

gcc -o 2 a.o b.o

原材料多了(重复定义) multiple definition

解决思路:多次实现了标签,只保留一个标签实现
在2个文件中都实现fun()函数,并重新编译,链接:

E:\temp>gcc -c -I./inc -o a.o 2.c

E:\temp>gcc -c  -o b.o abc.c

E:\temp>gcc -c -I./inc -o a.o 2.c

E:\temp>gcc -o 2 a.o b.o

提示错误:
E:\temp>gcc -o 2 a.o b.o
b.o:abc.c:(.text+0x0): multiple definition of `fun’
a.o:2.c:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

宏的使用

预处理的使用

#include 包含头文件,并在当前位置展开
#deine 宏(替换),不进行语法检查,编译时才检查
#define 宏名 宏体 加括号
#define ABC (5+3)
#define ABC(x) (5+(x)) //宏函数

预定义宏(方便调试)

(C语言编译器或gcc定义)
前后2个下划线
FUNCTIO
LINE
FILE

示例

#include <stdio.h>

int main()
{

     //本行执行的函数名,所在文件名,本行的行号
    printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);

    return 0;
}

输出:
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
the main,2.c,7

改示例为

#include <stdio.h>

int fun()
{
    int a;

     //本行执行的函数名,所在文件名,本行的行号
    printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);

    return 0;
}

int main()
{
    fun();

    return 0;
}

输出(实际调用的函数名称和所在行号):
E:\temp>cd “e:\temp” && gcc 2.c -o 2 && "e:\temp"2
the fun,2.c,8

条件预处理

#ifdef #else #endif
调试版本

发行版本
示例
原始代码:

#include <stdio.h>

int main()
{
    printf("=========================\n",__FILE__);

    printf("hello world!\n");

    return 0;
}

debug期间允许__FILE__行显示,但发行版本中不显示,怎么实现:

#include <stdio.h>

int main()
{
#ifdef  ABC

    printf("=========================\n",__FILE__);

#endif

    printf("hello world!\n");

    return 0;
}

未定义ABC时,不打印:

E:\temp>cd “e:\temp” && gcc 003.c -o 003 && "e:\temp"003
hello world!

需要显示调试信息时,只要在#ifdef ABC之前定义ABC即可。
在这里插入图片描述
但是该方法还是要修改源文件,不是很方便,故引入gcc -D:cpp之前增加define
如:gcc -DABC -o build 003.c 相当于编译前引入: #define ABC。

宏展开下的#、##

# 字符串化
## 连接符号
#define ABC(x) #x
#define ABC(x) day##x //day和x进行连接

示例

#include <stdio.h>
#define ABC(x)    #x //字符串化
#define DAY(x)    myday##x //字符串在当前位置展开,可以执行调用前,后缀
int main()
{
    int a;
    int myday1 = 10;
    int myday2 = 20;
     //本行执行的函数名,所在文件名,本行的行号
    // printf("the %s,%s,%d\n",__FUNCTION__,__FILE__,__LINE__);
    printf(ABC(ab\n));   //相当于:"ab\n"
    printf("the day is %d\n",DAY(1)); //前缀或者后缀以隐藏方式调用。
    printf("the day is %d\n",DAY(2));
    return 0;
}

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Medlar_CN/article/details/130157832