1、大致过程
C语言源代码文件.c
- 准备:编写hello.c
[root@hadoop1 make]# cat hello.c
include
int main() {
printf("hello world");getchar();return 0;
}
第一步:预处理
- gcc -E hello.c -o hello.i
- 生成hello.i文件
[root@hadoop1 make]# > gcc -E hello.c -o hello.i> [root@hadoop1 make]# ls
hello.c hello.i [root@hadoop1 make]# cat hello.i 此处省略。。。 extern char ctermid (char s) attribute ((nothrow__));
908 “/usr/include/stdio.h” 3 4
extern void flockfile (FILE stream) attribute ((nothrow__)); extern int ftrylockfile (FILE stream) attribute ((nothrow)) ; extern void funlockfile (FILE *stream) attribute ((nothrow));
938 “/usr/include/stdio.h” 3 4
2 “hello.c” 2
int main() { printf(“hello world”); getchar(); return 0; }
第二步:编译
- gcc -S hello.i -o hello.S
- 生成hello.S文件
[root@hadoop1 make]# gcc -S hello.i -o hello.S [root@hadoop1 make]# ls hello.c hello.i hello.S [root@hadoop1 make]# cat hello.s
.file "hello.c" .section .rodata.LC0:
.string "hello world" .text.globl main
.type main, @functionmain:
.LFB0:
.cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %eax movq %rax, %rdi movl $0, %eax call printf call getchar movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc.LFE0:
.size main, .-main .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-23)" .section .note.GNU-stack,"",@progbits
第三步:汇编
- gcc -c hello.S -o hello.o
- 生成hello.o文件
[root@hadoop1 make]# gcc -c hello.S -o hello.o
[root@hadoop1 make]# ls
hello.c hello.i hello.o hello.S [root@hadoop1 make]# cat hello.o
UH���H�Ǹ�����hello worldGCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-23)zRx
] �”A�C
.symtab.strtab.shstrtab.rela.text.data.bss.rodata.comment.note.GNU-stack.rela.eh_frame @”�H
&dd1d 90p.B�W�R �a� ��� "hello.cmainprintfgetchar��������
第四步:链接
- gcc hello.o -o hello
- 生成hello.文件,可直接运行
[root@hadoop1 make]# gcc hello.o -o hello
[root@hadoop1 make]# ls
hello hello.c hello.i hello.o hello.S
[root@hadoop1 make]# ./hello
hello world
总结
总共四个步骤
1、预处理 gcc -E hello.c -o hello.i 2、编译 gcc -S hello.i -o hello.S 3、汇编 gcc -c hello.S -o hello.o 4、链接 gcc hello.o -o hello
预处理 Pre-Processing
- 编译 Compiling
- 汇编 Assembling
- 链接 Linking
1、预处理 .h .c展开形成一个文件 .i 2、编译 .i生成一个汇编代码文件.S 3、汇编 .S生成一个.o 4、链接 .o链接成.exe/.elf
2、编译流程
第一步:编译
一般来说,无论是 C 还是 C++,首先要把源文件编译成中间代码文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件,即 Object File,这个动作叫做编译(compile)。
链接
然后再把大量的 Object File 合成执行文件,这个动作叫作链接(link)。 编译时,编译器需要的是语法的正确,函数与变量的声明的正确。 对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在 C/C++ 文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。 一般来说,每个源文件都应该对应于一个中间目标文件(.o 文件或 .obj 文件)。 链接时,主要是链接函数和全局变量。所以,我们可以使用这些中间目标文件(.o 文件或 .obj 文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File)。
在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便。所以,我们要给中间目标文件打个包,在 Windows 下这种包叫“库文件”(Library File),也就是 .lib 文件,在 UNIX 下,是 Archive File,也就是 .a 文件。
总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成 Object File。而在链接程序时,链接器会在所有的 Object File 中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在 VC 下,这种错误一般是:Link 2001 错误,意思说是说,链接器未能找 到函数的实现。你需要指定函数的 Object File。
3、gcc相关参数
相关参数
-o:指定生成的输出文件; -E:仅执行编译预处理; -S:将C代码转换为汇编代码; -wall:显示警告信息; -c:仅执行编译操作,不进行连接操作。
各种后缀名解释
.c C语言源代码文件 .i 经过预处理的C源代码文件 .S 经过预编译的汇编语言源代码 .o 编译后的目标文件
上述四部可以使用一行替换,将hello.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。
gcc hello.c
-o选项用来指定输出文件的文件名
gcc hello.c -o hello
换个顺序写也可以
gcc -o hello hello.c
