C/C++编译链接篇(一) 从源代码到可执行程序的过程

目录

一、从源代码到可执行程序的主要过程

二、linux环境下过程介绍

1.预处理

2.编译

3.汇编

4.链接

三、拓展

1.链接时如何靠.h文件中的声明找到对应.c文件下的定义?

2.在.h文件中定义全局变量

3.编译错误和链接错误


一、从源代码到可执行程序的主要过程

        预处理 -> 编译 -> 汇编 -> 链接


二、linux环境下过程介绍

1.预处理

        将后缀为.c的文件,处理成一个没有宏定义、没有条件编译指令、没有特殊符号、没有注释,后缀为 .i的文件。(.cpp/.cxx 则生成 .ii)

        a.头文件展开:将引用的头文件的内容复制到当前文件中。(这个过程是递归进行的,因为头文件中可能包含其他头文件)
        b.宏替换:展开所有的宏定义,即将文件中的所有宏名替换为相应的字符串。(C语言的宏替换和文件包含的工作,不归入编译器的范围,而是交给独立的预处理器)
        c.条件编译:#ifdef、#ifndef、#else、#elif、#endif等等。
        d.去掉注释
        e.保留所有的#pragma 编译器指令:编译器指令有特殊作用,编译器需要用到他们,如:#pragma once 是为了防止有文件被重复引用。
        f.添加行号和文件标识:便于编译时编译器产生调试用的行号信息,和编译时产生编译错误或警告是能够显示行号。

2.编译

        对xxx.i或xxx.ii文件,进行语法检查后生成相应的汇编代码文件(.s文件)。

        a.语法检查:词法分析、语义分析、符号汇总和语法分析及优化。        
        b.生成汇编代码:
在确认所有的指令都符合语法规则之后,将其翻译成。

3.汇编

        根据编译后生成的 .s文件,把汇编代码转换为二进制机器码,生成目标文件(.o(Windows下)、.obj(Linux下))

4.链接

        a.对于函数声明与定义都在不同文件里的文件,链接的作用就是将这些.o文件合并。
(如:函数声明在test.h中,定义在test.cpp中,use.cpp使用了其中的函数,链接时要将它们对应的.o文件合并。)

        b.除此之外,链接时还要确定变量、数组和函数的地址。

经过以上4个步骤,我们就得到了 可执行文件。(.exe文件、.out文件)

以下为linux环境下从源代码到可执行程序的过程简介图


三、拓展

1.链接时如何靠.h文件中的声明找到对应.c文件下的定义?

        借助符号表,存储变量和函数的地址映射。
        在.c文件汇编时在.o文件中会生成一个符号表,链接时根据变量名、函数名在对应.c文件的符号表中找到其地址,所以我们可以靠.h文件中的声明找到对应.c文件下的定义。

 2.在.h文件中定义全局变量

       所以我们要谨慎地在.h文件中定义全局变量,因为.h文件会在所有引用了它的地方展开,如果.h文件中有全局变量,又恰好又多个.c文件引用了.h文件,这样整个工程中会出现多个同名的全局变量,在符号表合并时该变量会有多个不同的地址,会导致链接错误。

       在.h文件中正确定义全局变量的方法是加一个extern使其变为声明,然后在存放定义的.c文件中对其进行定义,因为定义时变量和函数的地址才会进入符号表,这样在符号表合并时全局变量只有一个地址,不会导致链接错误。

       或是在.h文件将其定义为静态变量(static),修改其链接属性,使其变为当前文件可见,使其不再放入符号表中。即便展开后在引用了它的.c文件中会各自有一个静态变量,且这些静态变量的地址都不同,但其不会放入符号表中,其它文件不可见,故不会有链接错误。

eg.在头文件中定义全局变量

3.编译错误和链接错误

        a.编译错误:语法错误。
        b.链接错误:无法在其它文件中找到引用的函数、函数的重定义……

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烛火萤辉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值