GCC编译的背后(预处理和编、汇编和链接)
- 格式:pdf
- 大小:253.52 KB
- 文档页数:17
Gcc的编译流程分为了四个步骤,分别为:∙预处理(Pre-Processing)∙编译(Compiling)∙汇编(Assembling)∙链接(Linking)下面就具体来查看一下Gcc是如何完成四个步骤的。
首先,有以下hello.c源代码#include<stdio.h>int main(){printf("Hello! This is our embedded world!\n");return 0;}(1)预处理阶段在该阶段,编译器将上述代码中的stdio.h编译进来,并且用户可以使用Gcc的选项”-E”进行查看,该选项的作用是让Gcc在预处理结束后停止编译过程。
[root@localhost Gcc]# Gcc –E hello.c –o hello.i在此处,选项”-o”是指目标文件,由表3.6可知,”.i”文件为已经过预处理的C原始程序。
以下列出了hello.i文件的部分内容:typedef int (*__gconv_trans_fct) (struct __gconv_step *,struct __gconv_step_data *, void *,__const unsigned char *,__const unsigned char **,__const unsigned char *, unsigned char **,size_t *);…# 2 "hello.c" 2int main(){printf("Hello! This is our embedded world!\n");return 0;}由此可见,Gcc确实进行了预处理,它把”stdio.h”的内容插入到hello.i文件中。
(2)编译阶段接下来进行的是编译阶段,在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译成汇编语言。
【gcc】 gcc编译⼯具⽣成动态库(共享库)和静态库⽬录⼀、GCC 简介gcc作为编译⼯具,⽤在Linux操作系统中,可以编译C、C++、Object-C、JAVA等语⾔。
编译过程中可以带编译选项,选择编译过程。
GCC编译流程1)预处理 Pre-Processing2)编译 Compiling3)汇编 Assembling4)链接 LinkingGCC编译选项1、⼀般选项1) -c :只编译,不链接,⽣成⽬标⽂件“.o”。
2) -S :只编译,不汇编,⽣成汇编代码“.S”。
3) -E :只进⾏预编译/预处理,不做其他处理。
4) -o file:输出⽂件名为file5) -g :在可执⾏程序中包含标准调试信息。
6) -v :打印出编译器内部编译各过程的命令⾏信息和编译器的版本。
7) -I dir :在头⽂件的搜索路径列表中添加dir⽬录8) -L dir :在库⽂件的搜索路径列表中添加dir⽬录9) -static :连接静态库(静态库也可以⽤动态库链接⽅式链接)10) -llibrary :连接名为library的库⽂件(显⽰指定需要链接的动态库⽂件)-shared 该选项指定⽣成动态连接库l -fPIC:表⽰编译为位置独⽴的代码,不⽤此选项的话编译后的代码是位置相关的所以动态载⼊时是通过代码拷贝的⽅式来满⾜不同进程的需要,⽽不能达到真正代码段共享的⽬的。
l -ltest:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前⾯加上lib,后⾯加上.so来确定库的名称l LD_LIBRARY_PATH:这个环境变量指⽰动态连接器可以装载动态库的路径。
l 当然如果有root权限的话,可以修改/etc/ld.so.conf⽂件,然后调⽤ /sbin/ldconfig来达到同样的⽬的,不过如果没有root权限,那么只能采⽤输出LD_LIBRARY_PATH的⽅法了。
2、gcc告警和出错选项1) -ansi :⽀持符合ANSI标准的C程序2) -pedantic :允许发出ANSI C标准所列出的全部警告信息3) -pedantic-error :允许发出ANSI C标准所列出的全部错误信息4) -w :关闭所有警告5) -Wall :允许发出gcc提供的所有有⽤的报警信息6) -werror :把所有的告警信息转化为错误信息,并在告警发⽣时终⽌编译过程3、gcc优化选项1)-On:n的取值范围不⼀致,⽐较典型的范围为0变化到2或者3。
arm-linux-gcc常用参数讲解gcc编译器使用方法我们需要编译出运行在ARM平台上的代码,所使用的交叉编译器为arm-linux-gcc。
下面将arm-linux-gcc编译工具的一些常用命令参数介绍给大家。
在此之前首先介绍下编译器的工作过程,在使用GCC编译程序时,编译过程分为四个阶段:1. 预处理(Pre-Processing)2. 编译(Compiling)3. 汇编(Assembling)4. 链接(Linking)Linux程序员可以根据自己的需要让GCC在编译的任何阶段结束,以便检查或使用编译器在该阶段的输出信息,或者对最后生成的二进制文件进行控制,以便通过加入不同数量和种类的调试代码来为今后的调试做好准备。
和其它常用的编译器一样,GCC也提供了灵活而强大的代码优化功能,利用它可以生成执行效率更高的代码。
以文件example.c为例说明它的用法0. arm-linux-gcc -o example example.c不加-c、-S、-E参数,编译器将执行预处理、编译、汇编、连接操作直接生成可执行代码。
-o参数用于指定输出的文件,输出文件名为example,如果不指定输出文件,则默认输出a.out1. arm-linux-gcc -c -o example.oexample.c-c参数将对源程序example.c进行预处理、编译、汇编操作,生成example.0文件去掉指定输出选项"-o example.o"自动输出为example.o,所以说在这里-o加不加都可以2.arm-linux-gcc -S -o example.sexample.c-S参数将对源程序example.c进行预处理、编译,生成example.s文件-o选项同上3.arm-linux-gcc -E -o example.iexample.c-E参数将对源程序example.c进行预处理,生成example.i文件(不同版本不一样,有的将预处理后的内容打印到屏幕上)就是将#include,#define等进行文件插入及宏扩展等操作。
gcc编译c⽂件的⼏个过程https:///zhangpengshou/p/3587751.html/article/663750.htmlhttps:///LiuYanYGZ/p/5548855.htmlhttps:///qq_33160790/article/details/78887349c语⾔编译分为4个过程:1:预编译:预编译做的事情为:把伪指令转换为实际指令 命令 gcc -E a:#define a b b:#条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等 c:#include 头⽂件加⼊到编译的⽂件中 d:⼀些符号处理如file local 等等;# 1"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h"134# 211"/usr/lib/gcc/x86_64-redhat-linux/4.4.7/include/stddef.h"34typedef long unsigned int size_t;# 35"/usr/include/stdio.h"234# 1"/usr/include/bits/types.h"134# 28"/usr/include/bits/types.h"34# 1"/usr/include/bits/wordsize.h"134# 29"/usr/include/bits/types.h"234typedef unsigned char __u_char;typedef unsigned short int __u_short;typedef unsigned int __u_int;typedef unsigned long int __u_long;typedef signed char __int8_t;typedef unsigned char __uint8_t;typedef signed short int __int16_t;typedef unsigned short int __uint16_t;typedef signed int __int32_t;typedef unsigned int __uint32_t;typedef signed long int __int64_t;typedef unsigned long int __uint64_t;可以看出⼀个很⼩的程序经过编译以后把所有的头⽂件包含进来都是很⼤的2:编译 命令是 gcc -S 把预编译好的⽂件逐条转化为汇编语⾔ 优化阶段,经过预编译得到的输出⽂件中,只有常量;如数字、字符串、变量的定义, 以及c语⾔的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
GCC编译教程=======本教程将介绍GCC(GNU Compiler Collection)的基本概念和编译流程,包括预处理、编译、汇编和链接等步骤。
通过学习本教程,您将能够了解如何使用GCC编译C/C++程序,并进行深入的调试和优化。
1. 预处理(Preprocessing)-------------------预处理是编译流程的第一步,主要完成以下任务:* 宏替换:预处理器会根据源代码中的宏定义,将宏替换为相应的代码。
* 头文件展开:将源代码中包含的头文件展开,将头文件中定义的内容插入到源代码中。
* 条件编译:根据预定义的条件编译指令,如#if、#ifdef、#ifndef 等,对源代码进行条件编译,以生成不同的代码版本。
* 删除无用的头文件和宏定义:删除没有使用的头文件和宏定义,以减小编译结果的大小。
2. 编译(Compilation)------------------编译步骤将预处理后的源代码转换为汇编代码。
GCC使用不同的编译器来处理不同的编程语言,例如gcc用于C/C++,gfortran用于Fortran等。
编译器首先会将源代码转换为词法单元(token),然后将其转换为中间代码,最后将中间代码转换为汇编代码。
在编译过程中,编译器还会进行语法和类型检查,以确保源代码的正确性。
3. 汇编(Assembly)---------------汇编步骤将汇编代码转换为机器码。
GCC使用汇编器(assembler)将汇编代码转换为目标文件(.o文件),每个目标文件对应一个源代码文件。
目标文件包含了机器码和符号表信息,可以用于链接步骤。
4. 链接(Linking)-------------链接步骤将多个目标文件和库文件连接起来生成可执行文件。
链接器(linker)会根据符号表信息,将不同目标文件中的函数和变量链接在一起,以生成最终的可执行文件。
如果您的程序使用了外部库,链接器还会将库文件与目标文件进行链接。
gcc 编译流程gcc 是一种常用的编译器,被广泛应用于程序开发和编译过程中。
在了解 gcc 编译流程之前,我们先简单介绍一下编译的基本概念。
编译是将高级语言(如C、C++ 等)编写的源代码转换为机器语言(如汇编代码或机器指令)的过程。
编译器是用来进行编译的工具,而 gcc 就是其中较为常用的一个。
gcc 是GNU Compiler Collection(GNU 编译器集合)的缩写,它是一个由GNU 开发的自由软件项目,也是许多Unix-like 系统中默认的编译器。
gcc 支持多种编程语言,包括C、C++、Objective-C、Objective-C++、Fortran、Ada 等。
这里我们以C 语言为例,来介绍 gcc 的编译流程。
gcc 的编译过程可以分为四个主要阶段:预处理、编译、汇编和链接。
下面将详细介绍这四个阶段的具体操作和作用。
1. 预处理阶段:在预处理阶段,gcc 将源代码中的预处理指令进行处理,生成预处理后的代码。
预处理指令以"#" 开头,如"#include"、"#define" 等。
预处理的主要作用是对源代码进行宏替换、文件包含和条件编译等操作,以生成经过宏展开和文件合并后的代码。
2. 编译阶段:在编译阶段,gcc 将预处理后的代码转换为汇编代码。
汇编代码是一种与机器相关的低级语言,它是由一系列的机器指令组成。
编译的主要任务是对源代码进行词法分析、语法分析和语义分析等操作,以生成对应的汇编代码。
3. 汇编阶段:在汇编阶段,gcc 将汇编代码转换为机器代码。
机器代码是二进制的指令序列,可以被计算机直接执行。
汇编的主要作用是将汇编代码翻译成机器指令,生成可执行文件。
4. 链接阶段:在链接阶段,gcc 将多个源文件编译生成的目标文件进行链接,生成最终的可执行文件。
链接的主要作用是解决函数调用和变量引用等符号之间的关系,将多个目标文件合并成一个可执行文件。
编译的整个过程:预编译、编译、汇编、链接编译分为四个步骤:每个步骤将⽂件编译成别的格式,如下:详解:1.预编译:预编译过程主要做4件事:①展开头⽂件在写有#include <filename>或#include "filename"的⽂件中,将⽂件filename展开,通俗来说就是将fiename⽂件中的代码写⼊到当前⽂件中;②宏替换③去掉注释④条件编译即对#ifndef #define #endif进⾏判断检查,也正是在这⼀步,#ifndef #define #endif的作⽤体现出来,即防⽌头⽂件被多次重复引⽤2.编译将代码转成汇编代码,并且在这个步骤中做了两件很重要的⼯作:①编译器在每个⽂件中保存⼀个函数地址符表,该表中存储着当前⽂件内包含的各个函数的地址;②因为这步要⽣成汇编代码,即⼀条⼀条的指令,⽽调⽤函数的代码会被编译成⼀条call指令,call指令后⾯跟的是jmp指令的汇编代码地址,⽽jmp指令后⾯跟的才是“被调⽤的函数编译成汇编代码后的第⼀条指令”的地址,但是给call指令后⾯补充上地址的⼯作是在链接的时候做的事情。
3.汇编将汇编代码转成机器码4.链接编译器将⽣产的多个.o⽂件链接到⼀起⽣成⼀个可执⾏.exe⽂件;但是在这个过程中,编译器做的⼀个重要的事情是将每个⽂件中call指令后⾯的地址补充上;⽅式是从当前⽂件的函数地址符表中开始找,如果没有,继续向别的⽂件的函数地址符表中找,找到后填补在call指令后⾯,如果找不到,则链接失败。
举例:说实话,很多⼈做了很久的C/C++,也⽤了很多IDE,但是对于可执⾏程序的底层⽣成⼀⽚茫然,这⽆疑是⼀种悲哀,可以想象到⼤公司⾯试正好被问到这样的问题,有多悲催不⾔⽽喻,这⾥正由于换⼯作的缘故,所以打算系统的把之前⽤到的C/C++补⼀补。
这⾥权且当做抛砖引⽟,⼤神飘过。
【总述】从⼀个源⽂件(.c)到可执⾏程序到底经历了哪⼏步,我想⼤多数的⼈都知道,到时到底每⼀步都做了什么,我估计也没多少⼈能够说得清清楚楚,明明⽩⽩。
gcc编译过程的四个阶段1. 预处理(Preprocessing):预处理是编译过程的第一阶段。
预处理器负责对原始源文件进行处理,主要完成以下几个任务:-处理宏定义:预处理器会将源文件中的宏定义展开为相应的代码片段,并将其保存在一个临时文件中。
-处理条件编译指令:预处理器会根据条件编译指令的结果决定是否包含或排除一些代码片段。
- 处理#include指令:预处理器会将源文件中的#include指令所引用的其他文件插入到该指令所在的位置。
-移除注释:预处理器会删除源文件中的注释。
预处理后的文件成为扩展名为.i的中间文件,它包含了所有宏定义及展开后的代码。
编译是编译过程的第二阶段。
编译器将预处理生成的中间文件进行词法分析、语法分析和语义分析,生成相应的汇编代码。
主要过程如下:- 词法分析器将预处理生成的中间文件分解为一个个的词法单元(Token)。
- 语法分析器根据词法单元组织成的语法结构,生成抽象语法树(Abstract Syntax Tree,AST)。
-语义分析器对抽象语法树进行语义检查,包括类型检查和语义错误检查,确保程序的语义正确。
编译器将生成的汇编代码保存为扩展名为.s的汇编文件。
3. 汇编(Assembling):汇编是编译过程的第三阶段。
汇编器(Assembler)将编译器生成的汇编代码翻译成机器码,并生成目标文件。
具体过程如下:- 汇编器将汇编代码中的每一条汇编指令翻译成对应的机器码,同时为每个标号(Label)生成对应的地址。
-汇编器进行符号解析,将代码中引用的变量和函数与目标文件中的符号表进行匹配,生成正确的指令和地址。
汇编器将目标文件保存为扩展名为.o的目标文件。
4. 链接(Linking):链接是编译过程的最后阶段。
链接器(Linker)将目标文件与其他必要的库文件进行合并,生成最终的可执行文件或动态链接库。
主要过程如下:-链接器将目标文件中的函数和变量引用与其他目标文件中的定义进行匹配,解析外部引用,生成相应的引用表。
C++之gcc编译过程(原理)在平时gcc编译中,通常的⼀步编译操作为:gcc b.c -o b在使⽤gcc编译的过程中,那么这个⽂件编译过程到底是什么?上述gcc命令其实依次执⾏了四步操作:1.预处理(Preprocessing),2.编译(Compilation),3.汇编(Assemble),4.链接(Linking)。
⼀、预处理阶段在该阶段,会将b.h⽂件(头⽂件)中的宏定义、引⽤和⽂件中的符号定义替换为真正的内容。
预处理之后得到的仍然是⽂本⽂件,但⽂件体积会⼤很多。
这是因为预处理中做了⼀些符号替换操作。
注:预处理阶段不检查语法⽐如,在b.c头⽂件中引⽤了a.cpp/a.c,那么在预处理阶段,会将a.cpp/a.c中的符号加载到b.c中,这样才会在b.c中合理使⽤。
该阶段⽣成 .i 后缀⽂件gcc -E b.c -o b.i⼆、编译阶段该阶段是将经过预处理之后的程序转换成特定汇编代码的过程,该步会检查语法,通常编程报错就是在该阶段。
该阶段⽣成 .s后缀⽂件gcc -S b.i -o b.s三、汇编阶段汇编过程将上⼀步的汇编代码转换成机器码(machine code),这⼀步产⽣的⽂件叫做⽬标⽂件,是⼆进制格式。
该阶段⽣成 .o⽂件gcc -c b.s -o b.o四、链接阶段链接过程将多个⽬标⽂件以及所需的库⽂件(.so等)链接成最终的可执⾏⽂件。
需要启动代码、库代码等。
gcc b.o -o b 在该过程可以使⽤ldd b来查询需要哪些动态库。
(Windows中运⾏程序中的.dll⽂件,就是所需要的动态库)参数详解:。
gcc 多文件编译过程gcc多文件编译过程一、引言在软件开发过程中,我们经常会遇到需要将程序分成多个文件进行编写和管理的情况。
使用多文件编译可以提高代码的可读性、可维护性和可扩展性。
gcc是一款常用的编译器,本文将介绍gcc在多文件编译过程中的具体步骤和相关知识。
二、文件的组织和依赖关系在进行多文件编译前,我们首先需要了解文件的组织和依赖关系。
一般来说,一个程序由多个源文件(.c文件)和头文件(.h文件)组成。
源文件包含了程序的具体实现代码,而头文件则包含了函数声明和类型定义等信息。
源文件之间通过头文件进行相互调用和依赖。
三、编译的过程gcc在进行多文件编译时,主要包括了四个步骤:预处理、编译、汇编和链接。
1. 预处理预处理是在编译之前进行的一系列操作,主要包括宏展开、头文件包含、条件编译等。
预处理器会根据源文件中的指令,对代码进行相应的替换和处理。
处理后的代码被保存为.i文件。
2. 编译编译是将预处理后的代码转换成汇编代码的过程。
编译器会将.i文件中的代码进行语法分析和语义分析,并生成相应的汇编代码。
处理后的代码被保存为.s文件。
3. 汇编汇编是将汇编代码转换成机器码的过程。
汇编器会将.s文件中的汇编指令转换成机器码,并生成相应的目标文件。
处理后的目标文件被保存为.o文件。
4. 链接链接是将多个目标文件合并成一个可执行文件的过程。
链接器会根据目标文件之间的依赖关系,将它们合并成一个可执行文件。
在链接过程中,还会将程序所需要的库文件和系统函数链接到可执行文件中,以供程序运行时调用。
四、编译命令的使用在进行多文件编译时,我们需要使用gcc命令来进行编译操作。
gcc命令的基本格式如下:gcc [选项] 源文件1 源文件2 ... -o 输出文件其中,选项可以指定编译过程中的一些参数和选项,比如优化级别、调试信息等。
源文件是需要编译的源代码文件,可以是多个文件。
输出文件是编译生成的可执行文件的名称。
五、示例下面通过一个示例来演示gcc多文件编译的过程。
论坛搜索全文ZOL 论坛 > 技术论坛 > C/C++论坛 > GCC编译的背后( 预处理和编译 汇编和链接 )本主题共6楼ZOL_酋长 MySQL 版主离线 帖子 382 精华 24 技术分 1107注册时间 2005-08-25所在地 北京 所有帖子>> 复制本页连接给好友GCC编译的背后( 预处理和编译 汇编和链接 )by falcon2008-02-22 平时在Linux下写代码,直接用"gcc -o out in.c"就把代码编译好了,但是这后面到底做了什么事情呢?如果学习过编译原理则不难理解,一般高级语言程序编译的过程莫过于:预处理、编译、汇编、链接。
gcc在后台实际上也经历了这几个过程,我们可以通过-v参数查看它的编译细节,如果想看某个具体的编译过程,则可以分别使用-E,-S,-c和 -O,对应的后台工具则分别为cpp,cc1,as,ld 。
下面我们将逐步分析这几个过程以及相关的内容,诸如语法检查、代码调试、汇编语言等。
1、预处理开篇简述:预处理是C语言程序从源代码变成可执行程序的第一步,主要是C语言编译器对各种预处理命令进行处理,包括头文件的包含、宏定义的扩展、条件编译的选择等。
以前没怎么“深入”预处理,脑子对这些东西总是很模糊,只记得在编译的基本过程(词法分析、语法分析)之前还需要对源代码中的宏定义、文件包含、条件编译等命令进行处理。
这三类的指令很常见,主要有#define, #include和#ifdef ...#endif ,要特别地注意它们的用法。
(更多预处理的指令请查阅相关资料)#define除了可以独立使用以便灵活设置一些参数外,还常常和#ifdef ... #endif结合使用,以便灵活地控制代码块的编译与否,也可以用来避免同一个头文件的多次包含。
关于#include貌似比较简单,通过man找到某个函数的头文件,copy进去,加上<>就okay。
这里虽然只关心一些技巧,不过预处理还是蕴含着很多潜在的陷阱(可参考),我们也需要注意的。
下面仅介绍和预处理相关的几个简单内容。
打印出预处理之后的结果:gcc -E hello.c这样我们就可以看到源代码中的各种预处理命令是如何被解释的,从而方便理解和查错。
实际上gcc在这里是调用了cpp的(虽然我们通过gcc的-v仅看到cc1),cpp即The C Preprocessor,主要用来预处理宏定义、文件包含、条件编译等。
下面介绍它的一个比较重要的选项-D。
在命令行定义宏:gcc -Dmacro hello.c等同于在文件的开头定义宏,即#define maco,但是在命令行定义更灵活。
例如,在源代码中有这些语句。
#ifdef DEBUGprintf("this code is for debuggingn");#endif如果编译时加上-DDEBUG选项,那么编译器就会把printf所在的行编译进目标代码,从而方便地跟踪该位置的某些程序状态。
这样-DDEBUG就可以当作一个调试开关,编译时加上它就可以用来打印调试信息,发布时则可以通过去掉该编译选项把调试信息去掉。
本节参考资料:[1] C语言教程第九章:预处理/Article/kfyy/cyy/jc/200409/9.html[2] 更多/kfyy/c/6626.html/html/article/program/cpp/20071203/8745.html/bbs/programmer/2006-10-13/327.html2、编译(翻译)开篇简要:编译之前,C语言编译器会进行词法分析、语法分析(-fsyntax-only),接着会把源代码翻译成中间语楼主 发表于 2010-05-31 11:36:59 只看楼主 大 小登录 | 注册 | 论坛帮助ZOL首页 | 产品报价 | ZOL论坛首页 | 更多论坛言,即汇编语言。
如果想看到这个中间结果,可以用-S选项。
需要提到的是,诸如shell等解释语言也会经历一个词法分析和语法分析的阶段,不过之后并不会进行“翻译”,而是“解释”,边解释边执行。
************************A、解释程序所谓解释程序是高级语言翻译程序的一种,它将源语言(如BASIC)书写的源程序作为输入,解释一句后就提交计算机执行一句,并不形成目标程序。
就像外语翻译中的“口译”一样,说一句翻一句,不产生全文的翻译文本。
这种工作方式非常适合于人通过终端设备与计算机会话,如在终端上打一条命令或语句,解释程序就立即将此语句解释成一条或几条指令并提交硬件立即执行且将执行结果反映到终端,从终端把命令打入后,就能立即得到计算结果。
这的确是很方便的,很适合于一些小型机的计算问题。
但解释程序执行速度很慢,例如源程序中出现循环,则解释程序也重复地解释并提交执行这一组语句,这就造成很大浪费。
B、编译程序这是一类很重要的语言处理程序,它把高级语言(如FORTRAN、COBOL、Pascal、C等)源程序作为输入,进行翻译转换,产生出机器语言的目标程序,然后再让计算机去执行这个目标程序,得到计算结果。
编译程序工作时,先分析,后综合,从而得到目标程序。
所谓分析,是指词法分析和语法分析;所谓综合是指代码优化,存储分配和代码生成。
为了完成这些分析综合任务,编译程序采用对源程序进行多次扫描的办法,每次扫描集中完成一项或几项任务,也有一项任务分散到几次扫描去完成的。
下面举一个四遍扫描的例子:第一遍扫描做词法分析;第二遍扫描做语法分析;第三遍扫描做代码优化和存储分配;第四遍扫描做代码生成。
值得一提的是,大多数的编译程序直接产生机器语言的目标代码,形成可执行的目标文件,但也有的编译程序则先产生汇编语言一级的符号代码文件,然后再调用汇编程序进行翻译加工处理,最后产生可执行的机器语言目标文件。
在实际应用中,对于需要经常使用的有大量计算的大型题目,采用招待速度较快的编译型的高级语言较好,虽然编译过程本身较为复杂,但一旦形成目标文件,以后可多次使用。
相反,对于小型题目或计算简单不太费机时的题目,则多选用解释型的会话式高级语言,如BASIC,这样可以大大缩短编程及调试的时间************************把源代码翻译成汇编语言,实际上是编译的整个过程中的第一个阶段,之后的阶段和汇编语言的开发过程没有什么区别。
这个阶段涉及到对源代码的词法分析、语法检查(通过-std指定遵循哪个标准),并根据优化(-O)要求进行翻译成汇编语言的动作。
如果仅仅希望进行语法检查,可以用-fsyntax-only选项;而为了使代码有比较好的移植性,避免使用gcc的一些特性,可以结合-std和 -pedantic(或者-pedantic-erros)选项让源代码遵循某个C语言标准的语法。
这里演示一个简单的例子。
$ cat hello.c#includeint main(){printf("hello, worldn")return 0;}$ gcc -fsyntax-only hello.chello.c: In function ‘main’:hello.c:5: error: expected ‘;’ before ‘return’$ vim hello.c$ cat hello.c#includeint main(){printf("hello, worldn");int i;return 0;}$ gcc -std=c89 -pedantic-errors hello.c #默认情况下,gcc是允许在程序中间声明变量的,但是turboc就不支持hello.c: In function ‘main’:hello.c:5: error: ISO C90 forbids mixed declarations and codeZOL_酋长 MySQL 版主离线语法错误是程序开发过程中难以避免的错误(人的大脑在很多条件下都容易开小差),不过编译器往往能够通过语法检查快速发现这些错误,并准确地告诉你语法错误的大概位置。
因此,作为开发人员,要做的事情不是“恐慌”(不知所措),而是认真阅读编译器的提示,根据平时积累的经验(最好在大脑中存一份常见语法错误索引,很多资料都提供了常见语法错误列表,如和最后面的参考资料[12]也列出了很多常见问题)和编辑器提供的语法检查功能(语法加亮、括号匹配提示等)快速定位语法出错的位置并进行修改。
语法检查之后就是翻译动作,gcc提供了一个优化选项-O,以便根据不同的运行平台和用户要求产生经过优化的汇编代码。
例如,根据上面的简单演示,可以看出gcc有很多不同的优化选项,主要看用户的需求了,目标代码的大小和效率之间貌似存在一个“纠缠”,需要开发人员自己权衡。
$ gcc -o hello hello.c #采用默认选项,不优化$ gcc -O2 -o hello2 hello.c #优化等次是2$ gcc -Os -o hellos hello.c #优化目标代码的大小$ ls -S hello hello2 hellos #可以看到,hellos比较小,hello2比较大hello2 hello hellos$ time ./hellohello, worldreal 0m0.001suser 0m0.000ssys 0m0.000s$ time ./hello2 #可能是代码比较少的缘故,执行效率看上去不是很明显hello, worldreal 0m0.001suser 0m0.000ssys 0m0.000s$ time ./hellos #虽然目标代码小了,但是执行效率慢了些hello, worldreal 0m0.002suser 0m0.000ssys 0m0.000s相关热帖·我自己研发的极品五子棋,不服的进来比一比·大家来分析一下近来最火的电影《盗梦空间》的程序·实现线程分发·用C++连接MYSQL·浙大网新科技股份有限公司招IPHONE平台C++研发工个性签名 相濡以沫,不如相忘于江湖TOP 下面我们通过-S选项来看看编译出来的中间结果,汇编语言,还是以之前那个hello.c为例。
1楼 沙发 发表于 2010-05-31 11:37:25只看该作者帖子 382精华 24技术分 1107注册时间 2005-08-25所在地 北京 所有帖子>>不知道看出来没?和我们在课堂里学的intel的汇编语法不太一样,这里用的是AT&T语法格式。