GCC 编译一共分为4个阶段:预处理、编译、汇编、链接
gcc 【选项】要编译的文件【选项】【输出文件】
选项 | 说明 |
-E | 控制GCC编译器仅对源码做预处理操作 |
-S | 控制GCC编译器仅对指定文件处理之编译阶段 |
-c | 控制GCC编译器仅对制定文件处理至汇编阶段,并生成相应的目标文件 |
-o outfile | 指定输出文件的文件名 |
1. 预处理阶段(不会判断语法语句错误)
预处理阶段是编译的第一个阶段。在这个阶段,GCC会扫描源代码并执行以下操作:
①删除注释
②替换宏定义
③处理条件编译指令
将头文件插入源代码中(展开头文件)
gcc -E hello.c -o hello.i
预处理:指的是真正的C程序编译之前预先进行的一些处理步骤,这些预处理指令包括:
①头文件:#include
②定义宏:#define
③取消宏:#undef
④条件编译:#if、#ifdef、#ifndef、#else、#elif、#endif
⑤显示错误:#error
⑥修改当前文件名和行号:#line
⑦向编译器传送特定指令:#progma
- 一个逻辑行只能出现一条预处理指令,多个物理行需要用反斜杠连接成一个逻辑行;
2. 编译阶段
在预处理阶段之后,GCC会将源代码翻译成汇编代码,这个过程称为编译。编译器会检查源代码是否符合语法,以及是否存在语义错误。
在编译阶段,编译器将源代码翻译成汇编代码,以便下一步的汇编阶段使用。
gcc -S hello.i -o hello.s
3. 汇编阶段
汇编阶段是将汇编代码转换为机器代码的过程。在这个阶段,汇编器将汇编代码转换为机器指令,生成目标文件。
在汇编阶段,汇编器将汇编代码转换为机器指令,生成目标文件。
gcc -c hello.s -o hello.o
4. 链接阶段
链接阶段是将所有目标文件合并成一个可执行文件的过程。在这个阶段,链接器将目标文件中未定义的符号与其他目标文件中定义的符号进行匹配,并生成一个可执行文件。
在链接阶段,链接器将目标文件合并成一个可执行文件。
gcc hello.o -o hello
5、宏的概念
宏(macro)实际上就是一段特定的字串,在源码中用以替换为指定的表达式。例如:
#define PI 3.14
/*PI 就是宏(宏一般习惯用大写字母表达,以区分于变量和函数,但这并不是语法规定,只是一种习惯),
在程序中出现PI就替换成3.14*/
- 宏的作用:
- 使得程序更具可读性:字串单词一般比纯数字更容易让人理解其含义。
- 使得程序修改更易行:修改宏定义,即修改了所有该宏替换的表达式。
- 提高程序的运行效率:程序的执行不再需要函数切换开销,而是就地展开。
带参数的宏:
带参宏意味着宏定义可以携带“参数”,从形式上看跟函数很像,例如:
#define MAX(a, b) a>b ? a : b
#define MIN(a, b) a<b ? a : b
//带参数的宏最好加括号
#define MAX(a, b) (a)>(b) ? (a) : (b)
#define MIN(a, b) (a)<(b) ? (a) : (b)
注:带参数的宏,最好加上括号区分参数,避免参数是表达式从而系统编译错误;
6、宏定义中的符号粘贴
#include <stdio.h>
#define FUN_CALL(ch, n) _fun_##ch##_##n()
char _fun_aaa_2() {
return 'A';
}
int main(int argc, char *argv[]) {
printf("%c", FUN_CALL(aaa, 2)); //打印A
return 0;
}
字符串的宏
#include <stdio.h>
#define FUN_CALL(rt,h) "www."#rt".com."#h
int main(int argc,char *argv[])
{
printf("%s\n",FUN_CALL(baidu,http));
return 0;
}
输出:
www.baidu.com.http