通常的开发环境都是流行的集成开发环境(IDE)。这样的IDE一般都是将编译和链接的过程一步完成,通常将这种编译和链接合并到一起的过程称为构建。
2.1被隐藏了的过程
#include<stdio.h> int main() { printf("Hello World\n"); return 0; }
上面代码文件名为:hello.c,编译代码的过程可以分解为4个步骤:
- 预处理
- 编译
- 汇编
- 链接
2.1.1 预编译
源代码文件hello.c和相关头文件,如stdio.h等被预编译器cpp预编译成一个.i文件。
对于C++程序来说,源代码文件的扩展名可能是.cpp或.cxx,头文件的扩展名可能是.hpp,而编译后的文件扩展名是.ii。
如下图,我这里使用的是Ubuntu的系统:
这里编译上面的程序
这里可以看到生成了一个.i的文件,下面打开它:(只截取了文件开头和结尾)
预编译过程主要处理规则如下:
- 将所有的”#define”删除,并且展开所有宏定义。
- 处理所有条件预编译指令,比如”#if”
- 处理”#include”预编译指令,将包含的文件插入到该预编译指令的位置
- 删除所有注释”//”和”/**/”
- 添加行号和文件
- 保留所有的#pragme编译器指令,因为编译器需要使用它们
经过预编译后的.i文件不包含任何宏定义,因为所有的宏已经被展开。
2.1.2 编译
编译过程就是把预处理完的文件进行一系列词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件。现在版本的GCC把预编译和编译两个步骤合并成一个步骤,使用叫做ccl的程序来完成这两个步骤。
下面我们把预处理完的文件进行编译:
打开它看看
.file "hello.c" .section .rodata .LC0: .string "Hello World" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %edi call puts movl $0, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609" .section .note.GNU-stack,"",@progbits