编译过程:预处理、编译、汇编、链接
文章目录一、编译的过程1.原理2.gcc/g 编译指令(1)预处理 (-E)文本替换(2)编译 (-S)高级语言-汇编语言(3)汇编 (-c)汇编语言-机器码(4)链接 (无参数)目标文件库-可执行文件(5)四步合为一步3.举例(1)第一步预处理(2)第二步编译(3)第三步汇编(4)第四步链接一、编译的过程1.原理从源文件.cpp到可执行文件.exe的编译过程实际可拆分为4小步①预编译 ②编译 ③汇编 ④链接2.gcc/g 编译指令编译步骤参数核心作用输入文件默认输出命令1.预处理-E处理宏定义#define、头文件包含#include、条件编译#ifdef进行纯文本替换hello.c / .cpphello.ig -E hello.cpp -o hello.i2.编译(狭义)-S将高级语言(C/C)翻译为汇编语言生成汇编指令文件(.s文件)hello.ihello.sg -S hello.i -o my_asm.s3.汇编(狭义)-c将汇编语言翻译为机器码生成目标文件(.o/ .obj)。此时还未链接无法运行hello.shello.og -c hello.s -o my_lib.o大型项目最常用只编译修改过的文件4.链接无参数将多个目标文件.o和静态库/动态库合并解决符号引用生成最终的可执行程序hello.o 或 .cppLinux: a.outWindows: a.exeg hello.o -o hello.exe-o是output即重定向输出(1)预处理 (-E)文本替换1.预编译/编译预处理生成 【*.i】文件预处理后的源文件,将头文件进行了文本替换。代码总量就变长了变为上万行预处理器做了纯文本替换工作(1)头文件包含 (#include)找到对应的头文件 (比如 iostream)把它的全部内容复制粘贴过来替换掉这行 #include(2)宏展开 (#define)把代码中所有的宏标识符替换成定义好的文本(3)条件编译 (#ifdef / #ifndef / #endif)根据条件判断决定保留或丢弃某段代码只保留符合条件的代码。(4)删除注释并添加行号标记把 // 和 /* */ 删掉并插入 #line 指令告诉编译器哪一行代码原本来自哪个文件方便报错时定位。g-E test.cpp-o test.i(2)编译 (-S)高级语言-汇编语言2.编译-S把高级语言翻译为汇编语言生成【*.s】文件汇编文件高级语言→汇编语言g-S test.i-o test.s(3)汇编 (-c)汇编语言-机器码3.汇编把汇编语言翻译为机器代码(0101)生成目标文件.o / .obj Linux上为.o文件Windows上为.obj文件生成 【*.o】文件目标文件二进制文件g-c test.s-o test.o前三步 (预处理、编译、汇编) 也可合并为一步:g-c test.c-o test.o(4)链接 (无参数)目标文件库-可执行文件4.链接把静态库 静态链接or把动态库 动态链接生成可执行程序Windows.exe Linuxa.outgtest.o-o test(1)如果是静态库.a / .lib链接器会把库中你用到的机器码直接复制进你的可执行文件。(2)如果是动态库.so / .dll链接器不会复制代码而是只在可执行文件里记录一份“购物清单”告诉操作系统运行时去哪个路径加载这个库。(5)四步合为一步以上编译四步(预处理、编译、汇编、链接) 也可合并为一步:gtest.cpp-o test3.举例test_const.cpp(1)第一步预处理生成test.i(2)第二步编译生成 test.s(3)第三步汇编生成二进制机器码文件 test.obj.obj原文件可能是乱码用objdump -s或者objdump -d命令阅读(4)第四步链接生成可执行文件test.exe