gcc编译

基础学习——gcc编译

编译——就是一个将源代码翻译成计算机处理器能识别的语言的过程。

gcc

gcc是linux系统中通用的c编译器。

举例说明:

test.c

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

编译命令如下:

gcc test.c -o test

生成可执行文件test。实质上,上述编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和连接(Linking)。

1. 预编译(预处理Preprocessing)

预处理功能主要包括 宏定义、文件包含、条件编译 三个部分。
预处理过程读入源码,检查包含预处理指令的语句和宏定义,并对原代码进行相应的转换。预处理过程还会删除程序中的注释和多余的空白字符。

预处理指令 是指 以#开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。

gcc -E test.c -o test.i  //可以查看test.i,里面存放着test.c经过预处理后的代码
或者
gcc -E test.c //直接在命令行窗口中输出预处理后的代码
指令             用途
 #            空指令,无任何效果
 #include      包含一个源代码文件
 #define       定义宏
 #undef        取消已定义的宏
 #if          如果给定条件为真,则编译下面代码
 #ifdef        如果宏已经定义,则编译下面代码
 #ifndef       如果宏没有定义,则编译下面代码
 #elif         如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
 #endif        结束一个#if……#else条件编译块
 #error        停止编译并显示错误信息
 #else         略
 #error        指令将使编译器显示一条错误信息,然后停止编译。
 #line         指令可以改变编译器用来指出警告和错误信息的文件号和行号。
 #pragma       指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某 些烦人的警告信息。

应用代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SIX 6
#define SEVEN 7
#define Cube(x) (x)*(x)*(x)
#define VERSION "tzs"
#define PASTE(n) "最终胜利者是:"#n
#define NUM(a,b,c) a##b##c  // 其中 ##代表连接符,将a,b,c连接在一起
#define STR(a,b,c) a##b##c
#define DEBUG 1

int main()
{
    int i;
    i = SIX + SEVEN;
    printf("i = %d\n",i);
    i = (SIX * SEVEN);
    printf("i = %d\n",i);

    i = Cube(3);
    printf("i = %d\n",i);

    printf("%s",VERSION);
    printf("%s",PASTE(桃子));
    puts(PASTE(yy/));
    puts(PASTE(xx));

    printf("%d\n",NUM(1,2,3));
    //printf("%s\n",STR("aa","bb","cc"));

    #if DEBUG
        printf("Debugging\n");
        printf("Debugging2222\n");
    #endif
        printf("Running\n");
    #if defined DEBUG
        printf("yes\n");
    #endif
    #if !defined JJ
        printf("no JJ\n");
    #endif

}

参考:
http://blog.csdn.net/dotphoenix/article/details/4345174
http://www.cnblogs.com/ligongzi/archive/2012/08/24/2654732.html

2. 编译(Compilation,编译为汇编代码)

预处理之后,可以直接对生成的 test.i 进行编译,生成汇编代码:

gcc -S test.i -o test.s

gcc的-S选项,表示在程序编译期间,在生成汇编代码后,停止,-o输出汇编代码文件。

3. 汇编

对上面生成的汇编代码test.s,gas汇编器负责将其编译为目标文件。

gcc -c test.s -o test.o

gas汇编器是Linux平台的标准汇编器,它是gcc所依赖的后台汇编工具,通常包含在binutils软件包中。gas使用标准的AT&T汇编语法。

参考:http://www.oschina.net/question/234345_43024

4. 链接

gcc连接器是gas提供的,负责将程序的目标文件与所需的所有附加的目标文件连接起来,最终生成可执行文件。附加的目标文件包括静态连接库和动态连接库。(链接器程序可以实现 编译器的输出 与 编译程序所需要库 之间的链接)
对于上面生成的test.o,将其与C标准输入输出库进行连接,最终生成程序test。

gcc test.o -o test

运行./test即可输出“Hello World!”。

库是预编译的目标文件(object files)的集合,它们可被链接进程序。静态库以后缀为‘.a’的特殊的存档文件(archive file)存储。

标准系统库可在目录 /usr/lib 与 /lib 中找到。比如,在类 Unix 系统中 C 语言的数学库一般存储为文件 /usr/lib/libm.a。该库中函数的原型声明在头文件 /usr/include/math.h 中。

C 标准库本身存储为 /usr/lib/libc.a,它包含 ANSI/ISO C 标准指定的函数,比如‘printf’。对每一个 C 程序来说,libc.a 都默认被链接。

参考:http://www.cnblogs.com/fly1988happy/archive/2012/03/31/2427274.html

posted @ 2015-07-29 22:33  fly1988happy  阅读(400)  评论(0编辑  收藏  举报