1、大致过程

C语言源代码文件.c

  • 准备:编写hello.c

    [root@hadoop1 make]# cat hello.c

    include

    int main() {

    1. printf("hello world");
    2. getchar();
    3. 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, @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, %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