Linux C程序的编译过程


学习一门语言程序,本人觉得还是得学习它的编译规则,现在,通过小例子小结下自己对C编译的认识。

/*test.c     了解C程序的编译*/

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

对于test.c,我们常用一步编译到位的命令是:

gcc -o test test.c  或者  gcc test.c -o test

实际上,上面的这个编译命令包含了四个阶段的处理,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

如图:


这里详细列举完整的编译过程

预处理:

首先对源代码文件test.c和相关头文件,如stdio.h等被预编译器编译成一个.i 文件。

作用:  预处理的作用主要是读入源代码,检查包含预处理指令的语句和宏定义,并对源代码进行响应的转换。预处理过程还会删除程序中的注释和多余的空白字符。

对象:  预编译器主要处理那些源代码文件中的以“#”开头的预编译指令。比如“#include”、“#define”等,主要的处理规则如下:

1、将所有#define删除,并且展开所有的宏。

2、处理所有条件预编译指令,比如“#if”、“#ifdef”、“#elif”、“#else”、“#endif”。

3、处理“#include”预编译指令,将被包含的头文件插入到预编译指令的位置。这个过程是递归进行的,也就是说,包含的头文件也可能包含有其他头文件。

4、删除所有注释”//“和”/**/“。

5、添加行号和文件名注释,比如:#2”test.c“2,以便编译时编译器产生调试的行号信息及用于编译时产生编译错误和警告时能显示行号。

6、保留所有#pragma编译指令,因为编译器要使用它们。

经过预编译的.i文件不包含任何宏定义,因为所有的宏已经被展开,并且包含的头文件也已经插入到.i文件中。所以我们无法判断宏定义是否正确或头文件是否正确时,可以查看预编译后的文件来确定问题。

如上面的test.c文件的预处理指令是

gcc -E test.c -o test.i


编译-编译成汇编语言

编译过程是把预处理完的文件进行一系列词法分析、语法分析及优化后产生相应的汇编代码文件。

gcc -S test.i -o test.s

这是上面代码编译出来test.s的内容

.file "test.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, %edi
call puts
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-4)"
.section .note.GNU-stack,"",@progbits


汇编

作用:将上面的汇编指令编译生成目标文件

汇编器是将汇编代码转换成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令。所以汇编器的汇编过程相对于编译器来说比较简单,他没有复杂的语法,也没有语义、也不需要指令优化,只是根据汇编指令和机器指令对照表一一对应翻译就可以了。

gcc -c test.s -o test.o

这是上面的test.o文件的内容

ELF > 8 @ @
UH夊? ? ? 擅 hello world GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4) zR x? A?C
P .symtab .strtab .shstrtab .rela.text .data .bss .rodata .comment .note.GNU-stack .rela.eh_frame @ ? 0 & X , X 1 X 9 0 d - B ? W ? 8 R ? ? a x € ?
test.c main puts
?


链接

链接的主要目的是将程序的目标文件与所需要附加的目标文件链接起来,最终生成可执行文件。附加的目标文件也包括了所需要的库文件(静态链接库和动态链接库)

gcc test.o -o test

最终生成的test文件就是最终系统可以执行的文件。


对于程序的编译,我们一般把它认为“编译”和“链接”两部分也足够了,这里的编译已经包括了预处理,编译成汇编语言和编译成目标文件三个步骤了。只要头文件完整,语法无误,编译一般都能通过。只要有完整的目标文件和功能库文件,链接也可以成功。只要编译通过了,链接也通过了,整个项目的编译就算完成了。

Linux C程序的编译过程的更多相关文章

  1. WPF 程序的编译过程

    原文:WPF 程序的编译过程 基于 Sdk 的项目进行编译的时候,会使用 Sdk 中附带的 props 文件和 targets 文件对项目进行编译.Microsoft.NET.Sdk.WindowsD ...

  2. C#程序的编译过程

    C#程序的编译过程,如下图 总结:编译器将C#代码编译成DLL/EXE,DLL/EXE包含metadata(清单数据,对代码的描述)和IL(中间语言),IL(中间语言)经过CLR/JIT第二次编译才是 ...

  3. 关于一个程序的编译过程 zkjg面试

    http://blog.csdn.net/gengyichao/article/details/6544266 一 以下是C程序一般的编译过程: 从图中看到: 将编写的一个c程序(源代码 )转换成可以 ...

  4. Linux下Gcc 的编译过程

    在linux下开发难免会用到gcc编译.GCC(GNU Compiler Collection.GNU编译器套装),是由 GNU 开发的编程语言编译器.它是GNU编译器套装以GPL许可证所发行的自由软 ...

  5. 第一部分 记事本搞定第一个C#程序和编译过程剖析

    记事本搞定第一个C#程序 进行下面三个步骤:编码,编译和托管运行. 1.记事本进行编码: using System; class Program{ public static void Main() ...

  6. 【嵌入式开发】gcc 学习笔记(一) - 编译C程序 及 编译过程

    一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...

  7. gcc 学习笔记(一) - 编译C程序 及 编译过程

    一. C程序编译过程 编译过程简介 : C语言的源文件 编译成 可执行文件需要四个步骤, 预处理 (Preprocessing) 扩展宏, 编译 (compilation) 得到汇编语言, 汇编 (a ...

  8. Xilinx-Zynq Linux内核源码编译过程

    本文内容依据http://www.wiki.xilinx.com网址编写,编译所用操作系统为ubuntu 14 1.交叉编译环境的安装配置 1)http://www.wiki.xilinx.com/I ...

  9. Linux中程序的编译和链接过程

    1.从源码到可执行程序的步骤:预编译.编译.链接.strip 预编译:预编译器执行.譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的. 编译: 编译器来执行.把源码.c .S编程机器码. ...

随机推荐

  1. java笔记01-反射

    --2013年7月26日17:56:35 写文章之前,参考了这篇:http://www.cnblogs.com/Quincy/archive/2011/06/19/2084557.html 评价:这个 ...

  2. Shell学习笔记 - 运算符

    一.Declare命令 1. 命令格式 declare [+/-] [选项] 变量名 其中: -: 给变量设定类型属性 +:取消变量的类型属性 2. 参数说明 -i:将变量声明为整型 -a:将变量声明 ...

  3. 关于Class.forName("oracle.jdbc.driver.OracleDriver");报ClassNotFoundException 的异常

    关于try { Class.forName("oracle.jdbc.driver.OracleDriver"); }catch(ClassNotFoundException e) ...

  4. 小议jQuery中的事件

    学了jQuery这么长时间,到这里真的有一种柳暗花明又一村的感觉,在这里先表达一下自己学这一章节的happy心情吧(在严厉的金工实习老师眼皮底下偷偷学习,当然还有各种nerves~). 1加载DOM ...

  5. ASP.NET(C#) 读取EXCEL ——另加解决日期问题

    转载:http://www.cnblogs.com/diony/archive/2011/09/08/2171133.html 使用OLEDB可以对excel文件进行读取,我们只要把该excel文件作 ...

  6. 【整理修订】Android.mk详解

    Android.mk详解 1. Android.mk 的应用范围 Android.mk文件是GNU Makefile的一小部分,它用来对Android程序进行编译. 一个Android.mk文件可以编 ...

  7. 设置In_Memery

    alter system set inmemory_size=4G scope=spfile; alter table table_name inmemory; alter table table_n ...

  8. UIProgressView[进度条][一般型];UIStepper步数器][事件驱动型]

    ////  ViewController.m//  ProgressAndSteper////  Created by hehe on 15/9/21.//  Copyright (c) 2015年 ...

  9. 在button中加入一个view图片

    #import "ViewController.h" @interface ViewController () @end @implementation ViewControlle ...

  10. c# using 引用和别名的使用

    1.使用别名 在同时引用的两个命名空间中有相同的类型时,可以使用别名来区分.如下所示: using System; using System.Threading; using System.Timer ...