gcc对C语言的编译分为四个步骤:
预处理阶段会针对#开头的语句做处理,头文件和宏定义会展开直接插入到代码中,但是比如#if这样的判断会根据条件是否满足做展开处理。
#include <stdio.h> //预处理阶段此处会展开 #include "io.h" //预处理阶段会在此处展开 typedef struct { int a; char b; short c; }ST_HELLO; #define WHILE(value) while((value) < 10) //预处理阶段此处会展开 int main() { int i = 0; show("hello"); printf("%lu\n", sizeof(ST_HELLO)); WHILE(i+1) { printf("hello\n"); i++; } #if 0 //根据条件是否满足判断是否展开 printf("Yes\n"); #else printf("NO\n"); #endif }接下来用作预处理,gcc -E hello.c -o hello.i ; -E选项是预处理选项,-o则是输出命令,由于stdio.h太大了,这里只截取一部分
extern char *ctermid (char *__s) __attribute__ ((__nothrow__ , __leaf__)); # 912 "/usr/include/stdio.h" 3 4 extern void flockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ; extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)); # 942 "/usr/include/stdio.h" 3 4 # 2 "hello.c" 2 # 1 "io.h" 1 # 1 "io.h" extern void show(char *s); # 3 "hello.c" 2 typedef struct { int a; char b; short c; }ST_HELLO; int main() { int i = 0; show("hello"); printf("%lu\n", sizeof(ST_HELLO)); while((i+1) < 10) { printf("hello\n"); i++; } printf("NO\n"); }很明显,头文件宏定义被展开,#if 0语句也被去除,其他没有变化,甚至多打的换行业依然存在,接下来就是编译阶段了。
编译阶段会把展开后hello.i翻译成汇编语言:gcc -Og -S hello.c
.file "hello.c" .section .rodata.str1.1,"aMS",@progbits,1 .LC0: .string "hello" .LC1: .string "%lu\n" .LC2: .string "NO" .text .globl main .type main, @function main: .LFB23: .cfi_startproc pushq %rbx //将i压栈 .cfi_def_cfa_offset 16 .cfi_offset 3, -16 movl $.LC0,