C程序编译过程及优化选项介绍

  当我们编译了一个c文件,最终目的是让它能够成为可以执行的代码,就是能够受控或者控制硬件的东西。控制硬件的东西,一般都是二进制代码。那么,问题来了,从c到控制硬件的二进制代码,中间经过了一个什么流程呢?它的过程是这样的:

  一,编译预处理

    读取c源文件,对其中的伪指令(以#开头)和特殊符号进行处理;

    伪指令包括:宏定义: 比如:#defile PI (3.1415)

          条件编译:#if (conditions) {do something} #else {do another thing} #endif

               或#ifdef #ifndef #elif 等等。

          头文件:#include <filename>,  #include "filename"   头文件中的#ifndef __XXX_H__ #def __XXX_H__是为了防止避免头文件重复包含而导致程序出错。

    特殊符号:主要有__func__、__LINE__、__FILE__等

    预处理的工作其实就是将上面的伪指令和特殊符号展开,替换掉原来的c文件,这里不做语法的检查,仅仅是替换。

  二,编译阶段

    预处理后,进行的语法和词法的分析,确认指令都符合语法规则后,将其翻译成等价的中间代码或汇编代码。

  三,优化阶段

    中间代码的优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。

    偏向硬件执行的优化,考虑是如何充分利用机器的各个硬件寄存器存放的有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高。

  四,汇编过程

    将汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。OK,这里的意思就是汇编是将优化后的汇编代码,翻译成一个目标文件。但是这个这个目标文件能执行么?不能!!!因为在这个目标文件中,可能需要到其他库或者其他文件的一些函数,所以还要有一个链接的过程。这里先说说目标文件:

  目标文件由段组成。通常一个目标文件中至少有两个段:

    代码段  该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。

    数据段  主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。

  五,链接程序

    就是刚才说的汇编后生成的目标文件需要链接到一些库或者其他文件以获取自己源码内引用的函数,符号等。链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。

    链接分为静态和动态。静态就是涉及到的函数和符号,直接从源文件中copy过来,形成最终的可执行文件。动态只是记录这些函数和符号的一些信息,在执行的时候才从内存中查找,并映射到可执行文件的进程虚拟空间中。

    两种方式对比:静态的安全,但是可执行文件占用内存空间较大。动态的灵活,占用内存小,但是性能上可能会受到一些损害。

  经过这5步,一个c文件就可以被编译成可执行的文件,默认为a.out.

  参考:http://lavasoft.blog.51cto.com/62575/187229/

  关于优化选项的一些介绍:

    经常能看到gcc后有-O、-O1、-O2、-O3,这些代表什么意思呢?这些属于优化的选项,包括简化目标代码的长度,优化执行时间等。具体的参看下面的链接:

    中文的一些简介:http://blog.chinaunix.net/uid-23916171-id-2653114.html

    优化项的解释:http://gcc.gnu.org/onlinedocs/gcc-4.8.1/gcc/Optimize-Options.html#Optimize-Options

时间: 2024-10-14 00:49:10

C程序编译过程及优化选项介绍的相关文章

C语言程序编译过程

最近在编译DM8168的ARM端程序时经常出现未定义.重定义等报错,由于源码文件多,包含关系比较多,所以自己添加时容易乱.深深的体会到,好的代码风格是如此重要,之前也在看代码重构,以后应该更加注意代码的质量.经思考总结规律如下: 1.公用的数据结构等写为一个头文件,其他源文件包含此头文件.同时为了让不同源文件里的函数都可以使用,公用的函数可以放在此头文件中声明. 2.其他源文件里声明的变量,如果想在另一个文件里用,需要extern声明,这样可以避免各种全局变量的交互混杂. 理解的比较浅,希望高人

CUDA程序编译过程中产生警告的解决方法

有时候经常使用别人用Tabhost+其它的实现demo.单纯利用Tabhost该如何使用呢? 下面看例子: public class MainActivity extends TabActivity { public TabHost tabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 获取对象 tabHost = getTabH

李洪强iOS开发之C语言程序编译过程

汇编语言 指令用特定的名字来标记,这就是汇编语言 人比较容易看懂汇编语言 汇编直接和程序一一对应的 有汇编器把程序翻译成机器码 把高级语言编译成计算机识别的语言 程序编译过程 命令行 UNIX 系统中自带了C语言的编译器,编译器的名字叫CC CC 的含义是C Compler Linux系统是一个开源的,它自带的C编译器叫GCC GCC 不仅可以编译C 还可以编译Python 和OC MAC OS 的编译器是苹果公司自己研发的 Clang 在用CC或者GCC 的命令的时候,本质是调用了clang

liunx程序编译过程介绍及bug解决

1.  首先来看下一般的liunx中C程序具体的编译过程 参考网站http://blog.csdn.net/gengyichao/article/details/6544266上的图 将编写的一个.c文件(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译阶段和链接这两个主要阶段: 1) 编译阶段先通过“编译器”把一个.c 文件编译成 .s的汇编文件:再经过“汇编器”把这个.s的汇编代码汇编成.o 目标文件: 注:把预处理完的文件进行一系列的词法分析.语法分析.语义分析及优化后产生

Linux 程序编译过程的来龙去脉

大家肯定都知道计算机程序设计语言通常分为机器语言.汇编语言和高级语言三类.高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型,因此我们基本上将高级语言分为两大类,一种是编译型语言,例如C,C++,Java,另一种是解释型语言,例如Python.Ruby.MATLAB .JavaScript. 本文将介绍如何将高层的C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程,包括四个步骤: 预处理(Preprocessing) 编译(Compilati

linux程序编译过程

大家肯定都知道计算机程序设计语言通常分为机器语言.汇编语言和高级语言三类.高级语言需要通过翻译成机器语言才能执行,而翻译的方式分为两种,一种是编译型,另一种是解释型,因此我们基本上将高级语言分为两大类,一种是编译型语言,例如C,C++,Java,另一种是解释型语言,例如Python.Ruby.MATLAB .JavaScript. 本文将介绍如何将高层的C/C++语言编写的程序转换成为处理器能够执行的二进制代码的过程,包括四个步骤: 预处理(Preprocessing) 编译(Compilati

C程序编译过程浅析【转】

转自:http://blog.csdn.net/koudaidai/article/details/8092647 前几天看了<程序员的自我修养——链接.装载与库>中的第二章“编译和链接”,主要根据其中的内容简单总结一下C程序编译的过程吧. 我现在一般都是用gcc,所以自然以GCC编译hellworld为例,简单总结如下. hello.c源代码如下: ?[Copy to clipboard] C 1 2 3 4 5 6 [c] view plaincopy <span style=&qu

【转】android程序编译过程

现在很多人想对Android工程的编译和打包进行自动化,比如建立每日构建系统.自动生成发布文件等等.这些都需要我们对Android工程的编译和打包有一个深入的理解,至少要知道它的每一步都做了什么,需要什么环境和工具,输入和输出是什么.那么我们就来挖掘一下Android的编译过程中的细节. 首先,我们假定你的系统(什么系统都行,不限于Linux还是Windows系统,当然,我在这里默认使用Linux系统来举例子,但在 Windows中几乎没有什么差别)已经安装了JDK和Android SDK.再假

C程序编译过程浅析

前几天看了<程序员的自我修养——链接.装载与库>中的第二章“编译和链接”,主要根据其中的内容简单总结一下C程序编译的过程吧. 我现在一般都是用gcc,所以自然以GCC编译hellworld为例,简单总结如下. hello.c源代码如下: /* 何问起 hovertree.com */ int main() { printf(“Hello, world.\n”); return 0; } 通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out 其实编译(