Cpp程序的编译过程

2022-11-14 14:16:17 浏览数 (1)

前言

首先gcc与GCC要区分对待,GCC原名为GNU C Compiler,是一个C编译器的代号,但是后来不断地扩展,开始支持很多语言,GCC也就变成了编译器家族GNU Compiler Collection. 另外GNU的意思是GNU not Unix的递归简写(-_-所以那个G到底是啥意思?),这是一个由Stallman发起的一个操作系统计划,但是最后各种编译器什么的工具都写好了,核心的内核没有开发成功,但最后Linux填补了这个空白.

编译的四个阶段

如果只是在命令行编译一下c或c 程序,直接看后面的命令就可以了,但是了解一下编译的的过程,会加深对gcc的理解.

(环境:ubuntu 18.04 | 已安装gcc/g ) 1.预处理阶段 .c >>> .i 在这个阶段,编译器先把人方便看的程序处理成编译器方便看的程序.

#define删掉,然后展开所有宏定义

处理那些#include,把包含的那些头文件复制过来.

删掉注释

… 下面这个test.cpp

代码语言:javascript复制
#include <iostream> 
#include <cstdio> 
#define AA a*a 
 
using namespace std; 
 
int main(){ 
    int a=2; 
    int A=AA;//这里会用宏定义替换掉啊 
    cout<<A<<endl; 
    cout<<"hello world!"<<endl; 
    return 0; 
}

用命令 g -E test.cpp -o test.i 处理一下生成tes.i文件 (不加-o,就都会输出到屏幕上,不生成.i文件)

代码语言:javascript复制
此处省略两万行...
static ios_base::Init __ioinit;
}
# 2 "test.cpp" 2
# 1 "/usr/include/c  /7/cstdio" 1 3
# 39 "/usr/include/c  /7/cstdio" 3
# 40 "/usr/include/c  /7/cstdio" 3
# 3 "test.cpp" 2
# 5 "test.cpp"        //可以看到define,include
using namespace std;  // 什么的都没了,被替换为了上面两万多行

int main(){
 int a=2;
 int A=a*a;//此处宏定义被替换了,注释也没了
 cout<<A<<endl;
 cout<<"hello world!"<<endl;
 return 0;
}

2.编译为汇编代码 .i >>> .s 这一阶段,编译器进行:

  • 语法分析
  • 词法分析
  • 生成汇编代码 通过命令 g -S test.i -o test.s 可以生成汇编代码,代码太长,就不粘贴了.

3.生成机器码 .s >>> .o 通过 g -c test.s -o test.o 生成目标文件,如果程序只有一个文件,这时候应该就可以执行了.如果有多个.o文件,还得需要下一步链接后再运行. 这一步也可以用GNU自带的汇编器as来将汇编文件生成机器码,命令如下:

代码语言:javascript复制
as test.s -o test.o

这里可以借助hexdump工具来查看二进制文件

代码语言:javascript复制
hexdump -C test.o > a.txt
vim a.txt

4.链接.o文件 .o >>> 可执行文件

代码语言:javascript复制
g   test.o -o test
./test #然后就可以运行文件了

gcc & g

这两个都是编译器的名字,一般看名字会感觉gcc用来编译c语言,g 用来编译c 的,但实际上这两个既能编译c语言,又能编译c ,g 可以算是gcc的另一个版本. 当gcc编译c程序时 gcc a.c -o a #这样就生成可执行文件a了 当gcc编译c 程序时 gcc a.cpp -lstdc #加个-lstdc 链接上c 的库才行. 当g 编译c程序时,跟gcc用法是一样的,实际上g 在编译c程序是也是直接调用的gcc 当g 编译cpp程序时,看下面一节.

最最常用的命令

无论编译.c还是.cpp,g 都挺方便,一般直接都用g 就可以了. 有时候只是想快速的运行一个c或cpp程序而已,就不用看上面那一坨了…直接用这条命令就够了:

代码语言:javascript复制
g   test.cpp -o test  #cpp程序
./test #运行
------------------
g   test.c op test  #c程序
./test #

其他命令

代码语言:javascript复制
g   -c main.c #生成.o文件(.object)
g   -c main.c -o main.o #生成指定名字的.o文件
g   main.o #将main.o文件生成a.out文件(.obj >> .out)

常用选项

代码语言:javascript复制
-E	只运行 C 预编译器。
-S  生成汇编代码
-c	只编译并生成目标文件。
-g	生成调试信息。GNU 调试器可利用该信息。
-IDIRECTORY	指定额外的头文件搜索路径DIRECTORY。
-LDIRECTORY	指定额外的函数库搜索路径DIRECTORY。
-lLIBRARY	连接时搜索指定的函数库LIBRARY。
-o	FILE 生成指定的输出文件。用在生成可执行文件时。
-O0	不进行优化处理。
-O	或 -O1 优化生成代码。
-O2	进一步优化。
-O3	比 -O2 更进一步优化,包括 inline 函数。
-w	不生成任何警告信息。
-Wall	生成所有警告信息。

参考

C语言中文网 GCC编译c语言程序完整演示 c语言真正的编译过程 Linux查看二进制文件内容 GCC

欢迎与我分享你的看法。 转载请注明出处:http://taowusheng.cn/

0 人点赞