说说C/C++编译的那些事儿

一个稍稍令人惊讶的事实:C语言编译器其实是用C语言编写的。
——编者

广义的编译(compile)/构建(build),是将由源语言编写的一个或多个程序文件进行解析和转换,再结合共享库等资源,生成可以在目标机器上运行的可执行文件的过程。本书无意讨论编译器的详细工作原理,那是《编译原理》课程的内容。在这一章里,我们从使用者的角度,简单讨论编译及构建的过程概要。

本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载,但需要注明原作者"海洋饼干叔
叔";本文不允许以纸质及电子出版为目的进行抄摘或改编。
1.《Python编程基础及应用》,陈波,刘慧君,高等教育出版社。免费授课视频 Python编程基础及应用
2.《Python编程基础及应用实验教程》, 陈波,熊心志,张全和,刘慧君,赵恒军,高等教育出版社Python编程基础及应用实验教程
3. 《简明C及C++语言教程》,陈波,待出版书稿。免费授课视频

12.1 gcc编译示例

考虑到Linux操作系统及gcc编译器(GNU Compiler Collection)在工业界的基础性地位,本章的讨论以Linux操作系统及gcc编译器为基础。当然,读者也可以在Windows操作系统上使用mingw或其它编译器完成类似工作,详细过程请扫描二维码了解。

在一台树莓派4B卡片式计算机(gcc版本10.2.1,Linux内核版本5.15)上,作者在/home/pi/C12_Build目录下准备好了三个源代码文件,如图12-1所示。
图12-1 编译示例的源代码文件

💥
警告 树莓派4B基于一个使用ARM V8指令集的CPU,如果读者的计算机不基于ARM,且运行着非Linux系统,那么在后续操作中得到的编译及操作结果的细节可能与本书存在较大差异,但基本的流程和理论大体相当。

其中,文件compute.h的内容如下:

#ifndef _COMPUTE_H
#define _COMPUTE_H
#define PI 3.1415926  //comment
#define SQUARE(x)  x*x
float circleArea(const float r);
   
#endif

文件compute.c的内容如下,请注意作者有意在第1行和第2行重复引入了compute.h头文件。

#include "compute.h"
#include "compute.h"
   
float circleArea(const float r){
   
    float t = PI * SQUARE(r);  //comment
    return t;
}

文件area.c的内容如下:

#include <stdio.h>
#include "compute.h"
   
int main(){
   
    float r = 4.1f;
    float a = circleArea(r);   //comment
    printf("Area of the circle = %f.\n",a);
}

程序的结构极其简单:函数circleArea()根据圆的半径计算圆的面积,其声明位于compute.h,定义在compute.c中;文件area.c中的main()函数调用circleArea()计算半径为4.1的圆的面积,然后通过printf()打印到控制台。
图12-2 在终端里使用gcc编译示例程序并运行
我们在Linux终端(terminal)中依次执行了如表12-1所列的多个命令,完成了上述3个源代码文件的编译,并成功执行了名为area的可执行目标文件(executable object file),详见图12-2。在该图中,pi是操作系统用户名,MVE则是计算机名称。

表12-1 在终端里使用gcc编译示例程序并运行

命令 cd /home/pi/C12_Build
说明 将当前目录切换为/home/pi/C12_Build,示例的3个源代码文件在该目录里。cd是操作系统终端命令,意为改变目录(change directory)。
命令 ls (注意是字母l)
说明 终端命令,显示当前目录下的所有文件及子目录。执行结果显示当前目录下有area.c、compute.h及compute.c三个文件。
命令 gcc area.c compute.c –o area
说明 使用gcc编译器编译area.c及compute.c两个C语言程序文件,生成名为area的可执行目标文件。请注意,头文件compute.h不被视为一个单独的编译单元,所以未在命令中列出。上述命令行中的-o选项意为指定输出文件的名称。该文件执行完成后,再次执行ls,可见当前目录下多了一个名为area的文件,其绿色的文件名代表该文件是可执行目标文件。
命令 ./area
说明 载入并执行当前目录下名为area的可执行目标文件。在执行该命令后,操作系统会将该程序载入内存,然后将执行点转移至该程序的起始处。随后的执行结果可见,area成功计算并打印了半径为4.1的圆的面积。

图12-3展示了上述示例程序编译/构建过程的详细步骤。如图所示,构建过程至少包含预处理、编译、汇编和链接四个阶段。这里的编译是狭义的编译,其对应整个广义编译过程的第二个阶段:对预处理后的源程序文件进行解析,生成汇编语言代码文件。 图12-3 示例程序的编译/构建过程
同大多数编译器一样,C/C++也采用了分散编译(separate compilation)的技术。每个.c或者.cpp源代码文件被视为一个编译单元(compilation unit),编译器将程序中所有的编译单元逐一、分别进行预处理、编译和汇编,生成各自独立的可重定位目标文件(relocatable object file),然后再由链接器组合链接为一个整体的可执行目标文件(executable object file)。

12.2 预处理

预处理器主要完成下述任务:
(1) 对宏(macro)定义(#defin

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值