正文开始@Assassin
gcc/g++ 分别是linux环境下 C/C++ 的编译器,其基本使用方法:
[Assassin@Ninghai ~]$ gcc [选项] [编译文件] -o [可执行别名]
[Assassin@Ninghai ~]$ g++ [选项] [编译文件] -o [可执行别名]
执行编译好的可执行程序 test,该文件可以类比 win环境下的 test.exe 文件,linux 环境下运行可执行程序需要带上该文件的路径 (绝对路径 or 相对路径都可),在这里就是 ./ 也就是相对路径 当前文件夹下:
gcc/g++分别是GNU (GNU Compiler Collection) 的C/C++编译器,gcc及g++在执行翻译过程 (因为步骤中有编译步骤,这里为了不冲突说成翻译) 的时候一般有以下四个步骤:
.i
文件.s
文件.o
文件a.out
,可以用 -o
选项进行重命名语法: gcc/g++ [选项] [文件] -o [别名]
常用选项:
选项 | 具体含义 |
---|---|
-E | 只进行预处理,此操作不生成文件,需要把它重定向到一个输出文件里面(否则将把预处理后的结果打印到屏幕上) |
-S | 编译到汇编语言,不进行汇编和链接,即只进行预处理和编译 (默认会生成 .s 文件) |
-c | 编译到目标二进制代码,即只进行预处理,编译和汇编(默认会生成 .o 文件) |
-o | 将处理结果输出到指定文件,该选项后需紧跟输出文件名,可简单理解为重命名 |
-static | 此选项将采用静态链接的方式编译文件(gcc/g++默认编译是动态链接) |
-g | 添加调试信息生成debug版本,debug版本可使用gdb进行调试(若不携带该选项则默认生成release版本,release不可调试) |
-shared | 此选项将尽量使用动态库,生成文件较小 |
-w | 不生成任何警告信息 |
-Wall | 生成所有警告信息 |
-O0/-O1/-O2/-O3 | 编译器优化选项的四个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高 |
注:以下过程为演示g++的使用,gcc同理
预处理的功能主要包括宏定义替换,头文件包含,条件编译,去注释等;预处理指令主要指以 # 开头的语句
[Assassin@Ninghai c_code]$ g++ -E test.cc #完成预处理后停止
g++ -E 选项不会默认生成 .i 文件,也就是会把预处理信息打印在stdout上:
[Assassin@Ninghai c_code]$ g++ -E test.cc -o test.i #完成预处理后停止
编译时,gcc/g++ 会检查代码的规范性、是否有语法错误,用来确定代码实际所需要做的工作,检查无误后 gcc 会生成汇编代码
[Assassin@Ninghai c_code]$ g++ -S test.i -o test.s #完成编译后停止
注意:这里 -S 选项不带 -o 选项也可生成 test.s 文件,带上只是为了统一格式
汇编阶段将编译所形成的汇编代码再翻译生成可重定向目标二进制文件 .o 文件,对应到 win 环境下也就是 .obj 文件;虽说是二进制文件,但也不可执行
[Assassin@Ninghai c_code]$ g++ -c test.s -o test.o #完成汇编后停止
注意:这里 -c 选项不带 -o 选项也可生成 test.o 文件,带上只是为了统一格式
预处理,编译,汇编三个阶段统称为翻译(编译)过程,完成了上述编译的过程,就到了翻译环境的最后一个阶段:链接;将多个目标二进制文件链接之后便可生成可执行二进制文件
[Assassin@Ninghai c_code]$ g++ test.o -o test #链接完成
链接是将所有.c 源文件所生成的目标文件与语言的链接库文件绑定在一起进行链接;如图所示:
可以用 file 指令查看一下 test 文件的基本信息:
当然了,gcc/g++ 不带 -E,S,c 选项可一步到位生成可执行程序:
一般来说 -o 的使用有如下两种方式,共同点是 -o 后面跟的一定是生成的可执行文件而不是源文件,个人推荐第一种:
[Assassin@Ninghai c_code]$ g++ test.cc -o test # choice 1
[Assassin@Ninghai c_code]$ g++ -o test test.cc # choice 2
语言本身会提供链接库,库可以看成一套头文件和一套库文件;比如通常使用的 cout,cin 等库函数,都是在库文件中实现的,可以通过引用对应的头文件,来使用这些C语言已经为我们封装好的代码
使用 ldd 命令可以查看可执行程序所依赖的C/C++库:
Linux 环境下C/C++的库文件一般是 libc.a (libstdc++.a)和 libc.so (libstdc++.so),分别是静态库和动态库;Windows 环境下的静态库和动态库的后缀分别为.lib和.dll;
将用户所写的程序文件和第三方库提供的方法关联起来的过程称为链接;显然,链接又分为静态链接和动态链接,由上图可得知 test 文件的链接库是 .so,即 gcc/g++ 编译默认是动态链接;
静态链接和动态链接两者最大的区别就在于链接的时机不一样,静态链接是在形成可执行程序前,而动态链接的进行则是在程序执行时才开始链接
动态链接:
静态链接:
前面我们已经知道,gcc/g++默认采用的是动态链接的方式,这里也可以用 file 指令进行再一次验证:
虽然 gcc/g++ 默认采用的是动态链接,但如果需要使用静态链接,带上-static选项即可:
可以看到静态链接生成的文件确实比动态链接大得多 ^_^
之前我个人在使用 -static 静态编译时出现了诸如以下等类似的报错
/usr/bin/ld: cannot find -lc
查找了Stack Overflow后发现是我的云服务器缺少或者找不到 libc.a 静态库,解决方法是:
[Assassin@Ninghai c_code]$ sudo yum install -y glibc-static
安装之后应该是可以进行静态编译的~~