GCC
简介
Linux 下最常用的 C 编译器是 GCC,大多数发行版本都默认安装了 GCC。我们可以用以下 GCC 命令,把 test.c 编译成可执行文件 test:gcc -g test.c -o test。
如果大家习惯了 Visual Studio 等集成开发环境的话,会觉得上述的命令很费解。但掌握 GCC 等工具的用法,是一个程序员所必备的技能。
回到上面的 GCC 命令,它的作用是编译源文件 test.c 并生成可执行文件。其中 -o 表示生成的可执行文件名为 test,-g 表明要在可执行文件中添加调试信息。如果要使用 GDB 单步调试程序,必须使用 -g 参数。
可以看到,GCC 的行为是通过命令行参数进行指定的。所以,要掌握 GCC,重点在于熟悉 GCC 的各种参数上。但 GCC 的参数实在太多了,所以更普遍的做法是掌握其常用参数,并在遇到不认识的参数时多查资料进行学习。
GCC 的常用参数
-c
作用:只对源文件进行编译操作。
例子: gcc -c test.c
说明:这将生成目标文件(object file)test.o。
-E
作用:只对源文件进行预处理操作。
例子: gcc -E test.c > test.pre
-o
作用:指定输出文件(目标文件或者可执行文件)的文件名。
例子:gcc test.c -o test
说明:指定可执行文件的文件名为 test,否则默认为 a.out。
-D
作用:定义一个宏。
例子:gcc test.c -o test –DBIG_ENDIAN
说明:这和我们在源代码中加入语句 #define BIG_ENDIAN 的效果是一样的。
-M
作用:生成目标文件的依赖信息。
例子:执行 gcc -M test.c,输出结果如下所示。这表明要编译出目标文件 test.o,必须依赖源文件 test.c以及一堆的头文件。
1 | test.o: test.c/usr/include/stdio.h/usr/include/features.h \ |
说明:大家要记住 “依赖(dependency)” 这个新名词。在学习 Makefile 时,这个名词还会不断出现。
-O0/-O1/-O2/-O3
作用:O 是大写的英文字母 o,对应 Optimization。它指定编译器的优化选项,-O0 表示没有优化,-O1 为缺省值,-O3 优化级别最高。
例子:无
说明:只有对代码进行反汇编,我们才能看到这四个编译选项之间的差异。比如内联函数,在 -O0 作用下和普通函数无任何区别,仍需要显示调用;但在其他优化级别下,内联函数就会被直接嵌入被调用处。
-g
作用:-g 表明要在可执行文件中添加调试信息。如果要使用 GDB 单步调试程序,必须使用 -g 参数。
例子:无
说明:无
小结:上面只是列举了 gcc 的一小部分参数。如果在实际工作中遇到你不认识的参数,多使用 man gcc 命令学习。
ld、objdump、strip
以下简单介绍其他常用的编译、链接工具。在实际工作中,接触它们的机会相对较少,这里只作简单介绍。
ld:负责链接工作。较常用。
objdump:对目标文件和可执行文件进行反汇编。较常用。
例子:objdump –D test > test.S
strip:含义为 symbol table rip,它会删除目标文件或可执行文件中的符号表,在精简可执行文件的体积时会用到。
readelf:读取 elf 文件,并列出其详细信息,较少使用。
库依赖
有时候我们的代码要依赖标准库以外的库函数,如果库文件不在默认路径下,要显式地指明头文件/库文件的路径:
头文件用 -I;
库文件用 -L,用 -l 指明要寻找的库,例如引用 libcurl.so,则加上 -lcurl
例如:
1 | gcc test.c -I /home/curl/include -o test.o |

