C语言编译过程

  一个C代码到一个可执行程序,其中经历了预编译、编译和链接过程,最终生成可执行程序。

  1、编辑源代码hello.c

#include <stdio.h>
#define HELLO "Hello World!\n"
#define TEST
int main(void){
#ifdef TEST
    printf(HELLO);
#endif
    return 0;
}

  2、进行预编译

    预编译也叫预处理,本质上就是处理带‘#’的部分和注释,包括以下几部分:

    1)删除所有的注释。

    2)将#include包含的头文件直接拷贝到hello.c文件中。

    3)将所有的宏定义展开,也就是把所有的宏替换掉,并将#define删除。例子中是将printf中的HELLO用"Hello World!\n"进行了替换,最终是printf("Hello world!\n");。

    4)处理所有的条件编译指令,#ifdef、#ifndef、#endif等。例子中的#ifdef TEST,在预编译的过程中会检查是否定义了TEST这个宏,如果定义了就使用printf这个语句,如果没有定义什么也不做。

    5)#pragma特殊的指令,用的很少。

    6)添加行号和文件标识(#error、#line)用于调试和编译出错时。

//使用gcc -E hello.c -o hello.i生成预处理后的文件
[root@localhost compile_process]# gcc -E hello.c -o hello.i

//使用ls -lh看一下文件的大小
[root@localhost compile_process]# ls -lh
total 24K
-rw-r--r--. 1 root root 163 Nov 20 11:12 hello.c
-rw-r--r--. 1 root root 17K Nov 20 14:46 hello.i

  3、编译

    编译过程本质上就是把我们编写的代码翻译成机器语言的过程,这个过程都做了以下几步:

    1)词法分析

    2)语法分析

    3)语义分析

    4)优化后生成相应的汇编代码

//使用gcc -S hello.c -o hello.s生成汇编代码
[root@localhost compile_process]# gcc -S hello.i -o hello.s

//ls -lh
[root@localhost compile_process]# ls -lh
total 28K
-rw-r--r--. 1 root root 163 Nov 20 11:12 hello.c
-rw-r--r--. 1 root root 17K Nov 20 14:46 hello.i
-rw-r--r--. 1 root root 347 Nov 20 15:02 hello.s

  

//使用gcc -c hello.s -o hello.o将汇编文件生成二进制文件也就是机器能识别的语言
[root@localhost compile_process]# gcc -c hello.s -o hello.o
//ls -lh
[root@localhost compile_process]# ls -lh
total 32K
-rw-r--r--. 1 root root 163 Nov 20 11:12 hello.c
-rw-r--r--. 1 root root 17K Nov 20 15:08 hello.i
-rw-r--r--. 1 root root 856 Nov 20 15:15 hello.o
-rw-r--r--. 1 root root 347 Nov 20 15:08 hello.s

  4、链接

    在编译后只是生成了二进制文件,该文件不是可执行文件,要想得到可执行文件就要把二进制文件和C标准库绑到一起,这就是链接过程了。

//使用gcc hello.o -o hello生成可执行文件hello
[root@localhost compile_process]# gcc hello.o -o hello

//ls -lh
[root@localhost compile_process]# ls -lh
total 40K
-rwxr-xr-x. 1 root root 4.6K Nov 20 15:27 hello
-rw-r--r--. 1 root root  163 Nov 20 11:12 hello.c
-rw-r--r--. 1 root root  17K Nov 20 15:08 hello.i
-rw-r--r--. 1 root root  856 Nov 20 15:15 hello.o
-rw-r--r--. 1 root root  347 Nov 20 15:08 hello.s

//执行可执行文件hello
[root@localhost compile_process]# ./hello 
Hello World!

//使用ldd查看一下可执行程序所依赖的库信息
[root@localhost compile_process]# ldd hello
    linux-gate.so.1 =>  (0x00ad9000)
    libc.so.6 => /lib/libc.so.6 (0x003da000)
    /lib/ld-linux.so.2 (0x00572000)

  这就是我在使用gcc编译C程序是所经历的过程。当然可以在分细一点:预处理、编译、汇编、链接。还可以在分一下就是:预编译、编译、优化程序、汇编、链接。大体上就编译和链接两个阶段。

 

posted @ 2017-11-20 10:52  insistYuan  阅读(234)  评论(0编辑  收藏  举报