为了下面步骤解说的轻易,我们须要一个轻微庞杂一点的例子。假定我们本身定义了一个头文件mymath.h,完成一些本身的数学函数,并把细致完成放在mymath.c当中。然后写一个test.c顺序运用这些函数。顺序目次构造以下:
├── test.c └── inc ├── mymath.h └── mymath.c
顺序代码以下:
// test.c #include <stdio.h> #include "mymath.h"// 自定义头文件 int main(){ int a = 2; int b = 3; int sum = add(a, b); printf("a=%d, b=%d, a+b=%d\n", a, b, sum); }
头文件定义:
// mymath.h #ifndef MYMATH_H #define MYMATH_H int add(int a, int b); int sum(int a, int b); #endif
头文件完成:
// mymath.c int add(int a, int b){ return a+b; } int sub(int a, int b){ return a-b; }
1.预处理(Preprocessing)
预处理用于将一切的#include头文件以及宏定义替换成其真正的内容,预处理以后获得的依然是文本文件,但文件体积会大许多。gcc的预处理是预处理器cpp来完成的,你能够经由历程以下敕令对test.c举行预处理:
gcc -E -I./inc test.c -o test.i
或许直接挪用cpp敕令
$ cpp test.c -I./inc -o test.i
上述敕令中-E是让编译器在预处理以后就退出,不举行后续编译历程;-I指定头文件目次,这里指定的是我们自定义的头文件目次;-o指定输出文件名。
经由预处理以后代码体积会大许多:
X 文件名 文件大小 代码行数
预处理前 test.c 146B 9
预处理后 test.i 17691B 857
预处理以后的顺序照样文本,能够用文本编辑器翻开。
2.编译(Compilation)
这里的编译不是指顺序从源文件到二进制顺序的悉数历程,而是指将经由预处理以后的顺序转换成特定汇编代码(assembly code)的历程。编译的指定以下:
$ gcc -S -I./inc test.c -o test.s
上述敕令中-S让编译器在编译以后住手,不举行后续历程。编译历程完成后,将生成顺序的汇编代码test.s,这也是文本文件,内容以下:
// test.c汇编以后的效果test.s .file "test.c" .section .rodata .LC0: .string "a=%d, b=%d, a+b=%d\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $32, %esp movl $2, 20(%esp) movl $3, 24(%esp) movl 24(%esp), %eax movl %eax, 4(%esp) movl 20(%esp), %eax movl %eax, (%esp) call add movl %eax, 28(%esp) movl 28(%esp), %eax movl %eax, 12(%esp) movl 24(%esp), %eax movl %eax, 8(%esp) movl 20(%esp), %eax movl %eax, 4(%esp) movl $.LC0, (%esp) call printf leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE0: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
3.汇编(Assemble)
汇编历程将上一步的汇编代码转换成机器码(machine code),这一步发生的文件叫做目的文件,是二进制花样。gcc汇编历程经由历程as敕令完成:
$ as test.s -o test.o
等价于:
gcc -c test.s -o test.o
这一步会为每个源文件发生一个目的文件。因而mymath.c也须要发生一个mymath.o文件
4.链接(Linking)
链接历程将多个目的文以及所需的库文件(.so等)链接成终究的可实行文件(executable file)。
敕令大抵以下:
$ ld -o test.out test.o inc/mymath.o ...libraries...
结语
经由以上剖析,我们发明编译历程并不像设想的那末简朴,而是要经由预处理、编译、汇编、链接。只管我们日常平凡运用gcc敕令的时刻没有体贴中心效果,但每次顺序的编译都少不了这几个步骤。也不用为上述烦琐历程而懊恼,由于你依然能够:
$ gcc hello.c # 编译
$ ./a.out # 实行
以上就是c言语怎样编译(细致示例)的细致内容,更多请关注ki4网别的相干文章!