重学c语言系列一(gcc编译过程)

此系列文章的目的:1.希望能够掌握之前理解不清楚和根本没有掌握的知识点

                                    2 也算是一次复习,拓实基础,为笔试面试做准备吧

GCC 编译分为4个部分,预处理,编译,汇编,链接

假设源文件:test.c

预处理:

           命令如下:  gcc -E test.c -o test.i 
        参数-E表示只进行预处理,预处理器的活动:
     1.将所有的#define删除,并且展开所有的宏定义 
     2.处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等 
     3 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。 
     4 删除所有注释 “//”和”/* */”. 
     5 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。 
     6 保留所有的#pragma编译器指令,因为编译器需要使用它们 
示例:
#include<stdio.h>
#include<math.h>
#define YES 1
#ifdef YES
  printf("Yes, come here");
#else
  printf("Yes haven't been defined!");
#endif
  
int main()
{
    printf( "hello,world\n" );
    int x,y;/*x and y need to be assigned*/
    if(YES)  
     printf("%d, %d\n",x,y);  
    return 0;
}
结果部分代码,前面是stdio.h头文件内容:
extern int matherr (struct exception *__exc);
# 483 "/usr/include/math.h" 3 4

# 3 "relearn.c" 2
  printf("Yes, come here");

int main()
{
    printf( "hello,world\n" );
    int x,y;
    if(1)
     printf("%d, %d\n",x,y);
    return 0;
}
我们可以发现,之前的工作确实被完成了

编译:

   命令:gcc -S test.i -o test.s
   编译就是将源代码生成汇编代码,编译过程分为6步,词法分析,语法分析,语义分析,源代码优化,代码生成,目标代码优化
   编译原理中的知识:词法分析:就是将源代码的字符序列生成一个个词素或者记号(token)
                    记号的形式<记号名,属性值(指向符号表中的条目)>,lex工具可实现词法扫描
                    语法分析:根据第一步的词法单元生成语法分析树,yacc工具可实现语法分析
                    语义分析:使用语法树和符号表中信息检查源程序和语言定义的语义是否一致
                    源代码优化:即中间代码生成,将整个语法树转化为中间代码,中间代码和目标机器与运行环境无关的,
                                中间代码将编译器 分为前端和后端,前端负责产生与机器无关的中间代码,后端负责
                                将中 间代码转换为目标机器代码
                   目标代码生成与目标代码优化很容易理解

汇编:

   命令: gcc –c hello.c –o hello.o 
   汇编器将汇编代码生成汇编码,每个汇编语句几乎都对应一个机器指令,翻译过程类似查表

链接:

  链接的主要内容是:将各个模块相互间的引用处理好,主要过程包括:地址和空间分配,符号决议,重定位等

   链接分为静态链接和动态链接。

   静态链接:是在编译过程中吧静态库加入可执行文件中去,这样可执行文件比较大

   动态链接:是指链接阶段仅仅加入一些描述信息,程序执行时再吧相应动态库加载到内存中。

    在gcc下用到数学函数,如sqrt。在gcc时要加上 -lm 参数,这样告诉编译器我要用到数学函数了 。如:
         gcc a.c -o a -lm
   -l参数就是用来指定程序要链接的库,-l参数紧接着就是库名,那么库名跟真正的库文件名有什么关系呢?
    就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了。
    好了现在我们知道怎么得到库名了,比如我们自已要用到一个第三方提供的库名字叫libtest.so,那么我们只要把libtest.so拷贝到/usr/lib
    里,编译时加上-ltest参数,我们就能用上libtest.so库了(当然要用libtest.so库里的函数,我们还需要与libtest.so配套的头文件)。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值