gcc编译器的整个工作过程

gcc hello.c   ./a.out     或者 gcc hello.c -o hello   ./hello

./表示执行当前目录下的可执行程序或脚本程序。

首先gcc需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容;接着gcc会调用编译程序ccl和汇编程序as将处理后的源代码编译成目标代码;最后,gcc会调用链接程序ld,把生成的目标代码链接成一个可执行程序。其实gcc本身只是做了编译这一项工作,其余阶段的工作都是gcc调用其余服务程序来完成的。

预处理阶段。gcc把预处理命令扫描处理完毕,输入C语言的源文件(.c),这个阶段主要处理源文件中的#ifdef、#include、#define等预处理命令,该阶段会生成一个中间文件.i。可以使用-E参数让gcc在预处理阶段结束后停止编译过程,从而生成经过预处理的C源代码文件:gcc -E hello.c –o hello.i  vim hello.i  //查看该文件实际的变化      该阶段详细情况举例说明说明如下:

//head.h                              
#ifndef __HEAD_H__
#define __HEAD_H__

#define NUM1 10
#define NUM2 20
#endif



//sum.c
#include <stdio.h>  //直接在标准库中查找
#include "head.h"   //先在工作目录中查找,找不到再去标准库中查找
#define DEBUG     //去掉这一行,gcc编译时采用-D参数即可,生成最终文件时,不用-D参数。
int main(void)
{
    int a = NUM1;
    int aa;
    int b = NUM2;
    int sum = a + b;
    // 小盆友: 这是一个加法运算
#ifdef DEBUG
    printf("The sum value is: %d + %d = %d\n", a, b, sum);
#endif
    return 0;
}

如上段代码中,有两个文件,一个头文件head.h和一个c语言源代码文件sum.c。执行gcc -E sum.c -o sum.i后,打开sum.c可以看到如下内容:

//这上面还有很多内容,全是stdio.h头文件的内容
extern int ftrylockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__)) ;


extern void funlockfile (FILE *__stream) __attribute__ ((__nothrow__ , __leaf__));
# 943 "/usr/include/stdio.h" 3 4

# 2 "sum.c" 2
# 1 "head.h" 1
# 3 "sum.c" 2


int main(void)
{
    int a = 10;
    int aa;
    int b = 20;
    int sum = a + b;




    return 0;
}

可以看到在预处理过程中,预处理程序主要做了以下几件事情:1.处理#include,将所有头文件的内容都全部包含进来;2.处理掉所有的条件预编译命令,#ifdef   #ifndef  #endif等;3.删除所有的#define,并且展开所有的宏定义,即字符替换;4.删除所有注释;5.添加行号和文件标识,这样在调试和编译出错时才知道是哪个文件哪一行的问题;5.保留#pragma编译器指令,因为编译器在编译过程中需要使用它们。

#pragma para(其中para为参数)编译器指令的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma 指令对每个编译器给出了一个方法,在保持与C 和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。

编译阶段。gcc把预处理后的结果编译成汇编语言代码,输入的是.i,编译后生成汇编语言文件.s:gcc -S hello.i –o hello.s  vim hello.s    hello.s为汇编语言代码(没学过汇编的表示也看不懂!!)

汇编阶段。编译器把编译出来的汇编语言汇编成具体CPU上的目标代码(机器代码)。输入汇编代码文件.s,输出目标代码文件.o或.obj:gcc –c hello.s –o hello.o  vim hello.o  .o文件也是一个二进制代码文件,只是还不能执行,需要进行链接。

链接阶段。把多个目标代码模块链接成一个大的目标代码模块。输入目标代码文件.0(与其它的目标代码文件、库文件、引导代码),汇集成一个可执行的二进制代码文件:  gcc hello.o –o hello  vim hello       执行: ./hello    

后续(操作系统范畴):机器代码hello在操作系统机器上解释操作系统的;然后在机器语言机器上被翻译称为一个个微程序;最后,微程序的每一条微指令在微指令系统上执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值