c语言编译分为四步:
预处理->编译->汇编->链接
以下面的简单例子进行说明
main.c:
#include<stdio.h>
#define DEBUG(str){printf("%s\n",(str))}
int main()
{
#ifdef _DEBUG
DEBUG("hello");
#else
printf("hello\n");
#endif
return 0;
}
1.预处理
预处理阶段,预处理器会做这么几件事1)把注释全部过滤掉 2)宏定义替换 3)处理条件编译 4)include文件替换展开
使用gcc进行预处理的指令为 gcc -E main.c -o main.i
main.i:
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 367 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 410 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 411 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 368 "/usr/include/features.h" 2 3 4
# 391 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 392 "/usr/include/features.h" 2 3 4
# 28 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 1 3 4
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
# 216 "/usr/lib/gcc/x86_64-linux-gnu/5/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 34 "/usr/include/stdio.h" 2 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/types.h" 1 3 4
# 27 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 28 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;
typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
typedef long int __quad_t;
typedef unsigned long int __u_quad_t;
# 121 "/usr/include/x86_64-linux-gnu/bits/types.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/typesizes.h" 1 3 4
# 122 "/usr/include/x86_64-linux-gnu/bits/types.h" 2 3 4
extern int pclose (FILE *__stream);
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 "main.c" 2
# 5 "main.c"
int main()
{
printf("word\n");
return 0;
}
2.编译
编译阶段编译器会对语法进行检查纠错,生成汇编代码
使用gcc进行编译的指令为:gcc -S main.i -o main.s
main.s:
.file "main.c"
.section .rodata
.LC0:
.string "word"
.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.9) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
3.汇编
汇编阶段由编译器将汇编代码转为二进制机器码
使用gcc进行汇编的指令为:gcc -c main.s -o main.o
main.o:
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0100 3e00 0100 0000 0000 0000 0000 0000 ..>.............
00000020: 0000 0000 0000 0000 9802 0000 0000 0000 ................
00000030: 0000 0000 4000 0000 0000 4000 0d00 0a00 ....@.....@.....
00000040: 5548 89e5 bf00 0000 00e8 0000 0000 b800 UH..............
00000050: 0000 005d c377 6f72 6400 0047 4343 3a20 ...].word..GCC:
00000060: 2855 6275 6e74 7520 352e 342e 302d 3675 (Ubuntu 5.4.0-6u
00000070: 6275 6e74 7531 7e31 362e 3034 2e39 2920 buntu1~16.04.9)
00000080: 352e 342e 3020 3230 3136 3036 3039 0000 5.4.0 20160609..
00000090: 1400 0000 0000 0000 017a 5200 0178 1001 .........zR..x..
000000a0: 1b0c 0708 9001 0000 1c00 0000 1c00 0000 ................
000000b0: 0000 0000 1500 0000 0041 0e10 8602 430d .........A....C.
000000c0: 0650 0c07 0800 0000 0000 0000 0000 0000 .P..............
000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000000e0: 0100 0000 0400 f1ff 0000 0000 0000 0000 ................
000000f0: 0000 0000 0000 0000 0000 0000 0300 0100 ................
00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000110: 0000 0000 0300 0300 0000 0000 0000 0000 ................
00000120: 0000 0000 0000 0000 0000 0000 0300 0400 ................
00000130: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000140: 0000 0000 0300 0500 0000 0000 0000 0000 ................
00000150: 0000 0000 0000 0000 0000 0000 0300 0700 ................
00000160: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000170: 0000 0000 0300 0800 0000 0000 0000 0000 ................
00000180: 0000 0000 0000 0000 0000 0000 0300 0600 ................
00000190: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001a0: 0800 0000 1200 0100 0000 0000 0000 0000 ................
000001b0: 1500 0000 0000 0000 0d00 0000 1000 0000 ................
000001c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000001d0: 006d 6169 6e2e 6300 6d61 696e 0070 7574 .main.c.main.put
000001e0: 7300 0000 0000 0000 0500 0000 0000 0000 s...............
000001f0: 0a00 0000 0500 0000 0000 0000 0000 0000 ................
00000200: 0a00 0000 0000 0000 0200 0000 0a00 0000 ................
00000210: fcff ffff ffff ffff 2000 0000 0000 0000 ........ .......
00000220: 0200 0000 0200 0000 0000 0000 0000 0000 ................
00000230: 002e 7379 6d74 6162 002e 7374 7274 6162 ..symtab..strtab
00000240: 002e 7368 7374 7274 6162 002e 7265 6c61 ..shstrtab..rela
00000250: 2e74 6578 7400 2e64 6174 6100 2e62 7373 .text..data..bss
00000260: 002e 726f 6461 7461 002e 636f 6d6d 656e ..rodata..commen
00000270: 7400 2e6e 6f74 652e 474e 552d 7374 6163 t..note.GNU-stac
00000280: 6b00 2e72 656c 612e 6568 5f66 7261 6d65 k..rela.eh_frame
00000290: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000002d0: 0000 0000 0000 0000 2000 0000 0100 0000 ........ .......
000002e0: 0600 0000 0000 0000 0000 0000 0000 0000 ................
000002f0: 4000 0000 0000 0000 1500 0000 0000 0000 @...............
00000300: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000310: 0000 0000 0000 0000 1b00 0000 0400 0000 ................
00000320: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
00000330: e801 0000 0000 0000 3000 0000 0000 0000 ........0.......
00000340: 0b00 0000 0100 0000 0800 0000 0000 0000 ................
00000350: 1800 0000 0000 0000 2600 0000 0100 0000 ........&.......
00000360: 0300 0000 0000 0000 0000 0000 0000 0000 ................
00000370: 5500 0000 0000 0000 0000 0000 0000 0000 U...............
00000380: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000390: 0000 0000 0000 0000 2c00 0000 0800 0000 ........,.......
000003a0: 0300 0000 0000 0000 0000 0000 0000 0000 ................
000003b0: 5500 0000 0000 0000 0000 0000 0000 0000 U...............
000003c0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
000003d0: 0000 0000 0000 0000 3100 0000 0100 0000 ........1.......
000003e0: 0200 0000 0000 0000 0000 0000 0000 0000 ................
000003f0: 5500 0000 0000 0000 0500 0000 0000 0000 U...............
00000400: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000410: 0000 0000 0000 0000 3900 0000 0100 0000 ........9.......
00000420: 3000 0000 0000 0000 0000 0000 0000 0000 0...............
00000430: 5a00 0000 0000 0000 3500 0000 0000 0000 Z.......5.......
00000440: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000450: 0100 0000 0000 0000 4200 0000 0100 0000 ........B.......
00000460: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000470: 8f00 0000 0000 0000 0000 0000 0000 0000 ................
00000480: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000490: 0000 0000 0000 0000 5700 0000 0100 0000 ........W.......
000004a0: 0200 0000 0000 0000 0000 0000 0000 0000 ................
000004b0: 9000 0000 0000 0000 3800 0000 0000 0000 ........8.......
000004c0: 0000 0000 0000 0000 0800 0000 0000 0000 ................
000004d0: 0000 0000 0000 0000 5200 0000 0400 0000 ........R.......
000004e0: 4000 0000 0000 0000 0000 0000 0000 0000 @...............
000004f0: 1802 0000 0000 0000 1800 0000 0000 0000 ................
00000500: 0b00 0000 0800 0000 0800 0000 0000 0000 ................
00000510: 1800 0000 0000 0000 1100 0000 0300 0000 ................
00000520: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000530: 3002 0000 0000 0000 6100 0000 0000 0000 0.......a.......
00000540: 0000 0000 0000 0000 0100 0000 0000 0000 ................
00000550: 0000 0000 0000 0000 0100 0000 0200 0000 ................
00000560: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000570: c800 0000 0000 0000 0801 0000 0000 0000 ................
00000580: 0c00 0000 0900 0000 0800 0000 0000 0000 ................
00000590: 1800 0000 0000 0000 0900 0000 0300 0000 ................
000005a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
000005b0: d001 0000 0000 0000 1200 0000 0000 0000 ................
000005c0: 0000 0000 0000 0000 0100 0000 0000 0000 ................
000005d0: 0000 0000 0000 0000 ........
4.链接
链接由链接器把多个模块的引用相互协调,生成最终的可执行文件
gcc main.o -o main