• gcc编译


    基础学习——gcc编译

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

    gcc

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

    举例说明:

    test.c
    
    #include <stdio.h>
    int main(void){
    	printf("Hello world
    ");
    	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
    ",i);
        i = (SIX * SEVEN);
        printf("i = %d
    ",i);
    
        i = Cube(3);
        printf("i = %d
    ",i);
    
        printf("%s",VERSION);
        printf("%s",PASTE(桃子));
        puts(PASTE(yy/));
        puts(PASTE(xx));
    
        printf("%d
    ",NUM(1,2,3));
        //printf("%s
    ",STR("aa","bb","cc"));
    
        #if DEBUG
            printf("Debugging
    ");
            printf("Debugging2222
    ");
        #endif
            printf("Running
    ");
        #if defined DEBUG
            printf("yes
    ");
        #endif
        #if !defined JJ
            printf("no JJ
    ");
        #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

  • 相关阅读:
    C#结构体指针的定义及使用详解
    C# out和ref关键字
    CListCtrl控件主要事件及LVN_ITEMCHANGED消息和鼠标双击列表项事件的处理
    深圳职位:替朋友招聘biztalk的技术人员 无为而为
    微软出最新SQL Server 2005 累积修补程序包(版本 9.0.2153)(200684),这是SP1之后的更新 无为而为
    微软Visual Studio 2005 SDK version 3.0 发布了,TFS扩展的开发人员/DSL/VSTS Test都应该关注 无为而为
    好东西,将你的英文版TFS变为中文版?:Visual Studio 2005 Team Foundation Server 语言更改包 无为而为
    Analysis Service计算[期间增长率]的若干注意 无为而为
    亲身体验:更改 Team Foundation Server 部署的语言版本是一个复杂耗时的过程 无为而为
    各大门户调查:鄙视新浪,将博士伦的广告挂在热点新闻中间好几天了,把大众当傻瓜 无为而为
  • 原文地址:https://www.cnblogs.com/fly1988happy/p/4687721.html
Copyright © 2020-2023  润新知