gcc 编译可以执行程序4步分析
预处理:头文件展开,宏替换,注释去掉
编译:检查语法错误,将c语言变成汇编语言,消耗时间和系统资源最多
汇编:将汇编语言变成 二进制指令
链接:数据段合并以及地址回填,将函数库中相应的代码组合到目标文件中
gcc编译参数
gcc nginx.c -o b.out -I /home/hunandede/head/ -g
-I 表示指定头文件的位置,在 /home/hunandede/head/下,-I 和 头文件位置中间没有空格。
-g 表示 包含调试信息。加上-g 就可以使用GDB工具调试了。
-Wall 提示更多的警告信息,假设代码中我们有一个int a ,但是这个a 从来没有使用过,就会有警告在编译阶段出现。 这个一般也在GDB调试的时候加上。
-D<DEF> 编译时定义一个宏,类似于在代码中有一个宏定义
我们来看一段代码,在main函数中要打印 HI,但是这个HI 只有在定义了HELLODEBUG 这个宏的时候才会有值:如下code
#include <stdio.h>
#define HELLODEBUG
#ifdef HELLODEBUG
#define HI 20
#endif // HELLODEBUG
int main() {
printf("HI = %d\n",HI);
return 0;
}
如果我们现在将代码中 如下的一行删除了,那么肯定就有build error 了
#define HELLODEBUG //删除了
改动代码为:
#include <stdio.h>
//#define HELLODEBUG
#ifdef HELLODEBUG
#define HI 20
#endif // HELLODEBUG
int main() {
printf("HI = %d\n",HI);
return 0;
}
hunandede@hunandede-virtual-machine:~/aaa$ gcc cptest.c -o cptest.out -g -Wall
cptest.c: In function ‘main’:
cptest.c:11:21: error: ‘HI’ undeclared (first use in this function)
printf("HI = %d\n",HI);
^
cptest.c:11:21: note: each undeclared identifier is reported only once for each function it appears in
hunandede@hunandede-virtual-machine:~/aaa$
这时候这个 -D<DEF> 就有用了,可以改动为
gcc cptest.c -o cptest.out -g -Wall -D HELLODEBUG
hunandede@hunandede-virtual-machine:~/aaa$ gcc cptest.c -o cptest.out -g -Wall -D HELLODEBUG
hunandede@hunandede-virtual-machine:~/aaa$ ./
b.out cptest.c cptest.out nginx.c test.c test.out
hunandede@hunandede-virtual-machine:~/aaa$ ./cptest.out
HI = 20
hunandede@hunandede-virtual-machine:~/aaa$
有啥用? 开发阶段加 log
#include <stdio.h>
int main() {
#ifdef MTKDEBUG
printf("debug on goingi\n");
#endif
return 0;
}
在代码开发阶段,就可以加上这个参数,开发完成后,编译的时候只要不加这个 宏就没有问题了。
hunandede@hunandede-virtual-machine:~/aaa$ gcc canusetest.c -o canusetest.out
hunandede@hunandede-virtual-machine:~/aaa$ ./canusetest.out
hunandede@hunandede-virtual-machine:~/aaa$ gcc canusetest.c -o canusetest.out -D MTKDEBUG
hunandede@hunandede-virtual-machine:~/aaa$ ./canusetest.out
debug on goingi
hunandede@hunandede-virtual-machine:~/aaa$
gcc编译阶段可能出错的地方和信息:
预处理 可能会出错,这时候错误信息会包含行号
编译 可能会出错,这时候错误信息会包含行号
汇编 一般汇编不会出错
连接 可能会出错,由于已经经过了汇编,因此错误在这里不会有行号,会有collect2:error :ld returned 1 exit status 之类的提示;一般情景:当我们使用 静态库和动态库的时候,