目录
1. gcc遵守的约定规则
概述:gcc是将C/C++文件,通过预编译、编译、汇编、链接生成可执行文件
1.1 gcc的文件类型约定
1.2 gcc的选项参数
2. gcc的编译过程
gcc [选项] 文件名
gcc 与 g++ 分别是 gnu 的 c & c++ 编译器 gcc/g++ 在执行编译工作的时候,总共需要4步:
- 1、预处理,生成 .i 的文件[预处理器cpp]
- 2、将预处理后的文件转换成汇编语言, 生成文件 .s [编译器egcs]
- 3、有汇编变为目标代码(机器代码)生成 .o 的文件[汇编器as]
- 4、连接目标代码, 生成可执行程序 [链接器ld]
(1)预处理
在预处理阶段,gcc会把预处理的命令扫描并处理完毕(头文件、宏定义、宏函数),该阶段会生成.i的文件
gcc -E 文件名.c -o 文件名.i
gcc -o 文件名.i -E 文件名.c
gcc -E -o 文件名.i 文件名.c
gcc -o 文件名.i 文件名.c -E
(2)编译
在编译阶段,gcc把预处理结果编译成汇编或目标模块,生成.s文件
gcc -S 文件名.c -o 文件名.s
gcc -o 文件名.s -S 文件名.c
gcc -S -o 文件名.s 文件名.c
gcc -o 文件名.s 文件名.c -S
(3)汇编
在汇编阶段,编译器把编译出来的结果生成具体的CPU上的目标代码,生成.o文件
gcc -C 文件名.c -o 文件名.o
gcc -o 文件名.o -C 文件名.c
gcc -C -o 文件名.o 文件名.c
gcc -o 文件名.o 文件名.c -C
(4)链接
在链接阶段,将一个个生成的.o文件,链接起来生成可执行文件,在Windows上是.exe,Linux上是.out
gcc test.o -o test
gcc -o test.c test.o
gcc -o test test1.c test2.c test3.c
gcc test1.c test2.c test3.c -o test2
3.常用参数
3.1 预处理
不支持多文件操作,单一文件见前文
3.2 编译
多文件:默认按照源文件,生成对应的同名.s文件
gcc -S test1.c test2.c test3.c
gcc test1.c test2.c test3.c -S
3.3 汇编
多文件:默认按照源文件,生成对应的同名.o文件
gcc -c test.c test1.c test2.c
gcc test.c test1.c test2.c -c
3.4 生成可执行文件
gcc -o test.c test1.c test2.c
gcc test.c test1.c test2.c -o
3.5 生成可执行程序系统默认名
gcc test.c test1.c test2.c -o a.out
3.6 包含调试信息 -g
1.无调试信息
gcc test.c test1.c -o test
2.有调试信息,程序会变大
gcc test.c test1.c -o test -g
3.7 代码优化O(n)
代码优化指的是编译器通过分析源代码,找其尚未达到最优的部分,然后对其重新进行组合,目的是改善程序的执行性。本质上是缩短了程序的运行时间。
默认无优化
gcc test.c -o test
调整为o2优化
gcc test.c -o test1 -o2
结果查看:
time ./test
time ./test1
3.8 提示警告
gcc有很多编译选项,警告选项:指定头文件、库路径;优化选项。
默认级别是编译器认为的警告,满足大部分场合使用
(1) 显示更多警告wall
方便检查代码的安全性
(2)发生第一个错误中止编译 Wfatal-errors
(3)关闭警告 -w(不要使用)
(4)警告转换为错误 Werror
3.9 检查是否符合C语言标准
gcc -pedantic warning_code.c -o warning_code
4 程序库
- 程序库
什么是库
在 windows 平台和 Linux 平台下都大量存在着库。
本质上来说库是 一种可执行代码的二进制形式,可以被操作系统载入内存执行。
由于 windows 和 linux 的平台不同(主要是编译器、汇编器和连接器 的不同),因此二者库的二进制是不兼容的。
linux 下的库有两种:静态库和共享库(动态库)。
二者的不同点在于代码被载入的时刻不同。
静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。
静态用.a为后缀, 例如: libhello.a
共享库(动态库)的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
动态通常用.so为后缀, 例如:libhello.so
共享库(动态库)的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
4.1创建和使用静态库
ar rcs libname.a file1.o file2.o
ar -rcs libname.a file1.o file2.o
表示要把目标码file1.o和file2.o加入到静态库libname.a中。只有那么是可以修改的,其他是固定的。
Linux静态库命名规范,必须是"lib[your_library_name].a":lib为前缀,中间是静态库名,扩展名为.
通过上面的流程可以知道,Linux创建静态库过程如下:
- 首先,将代码文件编译成目标文件.o(StaticMath.o)
g++ -c StaticMath.cpp
注意带参数-c,否则直接编译为可执行文件
- 然后,通过ar工具将目标文件打包成.a静态库文件
ar -crv libstaticmath.a StaticMath.o
生成静态库libstaticmath.a。
大一点的项目会编写makefile文件(CMake等等工程管理工具)来生成静态库,输入多个命令太麻烦了。
Linux下使用静态库,只需要在编译的时候,指定静态库的搜索路径(-L选项)、指定静态库名(不需要lib前缀和.a后缀,-l选项)。
# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath
- -L:表示要连接的库所在目录
- -l:指定链接时需要的动态库,编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a或.so来确定库的名称。