一、不同环境下C语言的编译
1、Ubuntu20.04下用gcc编译
(1)程序编写
程序已经用vi写好,以下使用cat命令展示
- main.c
- sub1.h
(2)gcc命令编译
多个文件一起编译,并将输出放在main1中
- `gcc`是编译器的调用命令。当执行这个命令时,`gcc`首先会对文件进行预处理、编译、汇编和链接这一系列操作。
- 预处理:在预处理阶段,`gcc`会处理源文件中的预处理指令,例如`#include`指令。对于`#include <stdio.h>`这样的指令,编译器会将`stdio.h`头文件的内容插入到`main.c`源文件中,这个过程是为了引入必要的函数声明、宏定义等信息。
- 编译:将预处理后的C语言代码转换成汇编语言代码。这个阶段会检查C语言语法是否正确,例如检查变量定义是否符合规则、函数调用是否正确等。如果代码存在语法错误,编译器会在这里报错并停止编译。
- 汇编:把汇编语言代码转换成机器语言指令,生成目标文件。目标文件通常以`.o`为扩展名,不过在这个完整的命令中,由于使用了`-o`选项,最终不会生成中间的`.o`文件(如果没有`-o`选项,会生成一个默认名称的目标文件,如`main.o`)。
- 链接:链接阶段是将目标文件和系统库以及其他需要的目标文件(如果有)连接在一起,生成最终的可执行文件。例如,如果`main.c`文件中调用了`printf`函数(来自`stdio.h`头文件),链接器会将`printf`函数的实现代码从标准C库中链接到最终的可执行文件中
- `-o`选项的作用:`-o`是一个输出选项,用于指定生成的可执行文件的名称。在`gcc main.c sub.h -o main1`命令中,`-o main1`表示将生成的可执行文件命名为`main1`。如果省略这个选项,`gcc`会生成一个默认名称的可执行文件,通常是`a.out`
(3)运行结果
执行`./main1`或者`./a.out`即可编译生成程序,这里使用的是`./main1`
2、Windows11下用Dev-c++编译
(1)程序编写
- main1.c
- sub1.c
(2)编译运行结果
二、Makefile方式进行编译
1、Makefile文件编写规则
Makefile 由一系列规则组成,每个规则包含目标(target)、依赖(prerequisites)和命令(commands)三部分。目标是要生成的文件或要执行的操作,依赖是生成目标所需要的文件或其他目标,命令则是为了从依赖生成目标所需要执行的 shell 命令。
具体形式如下:
target:prerequisites
command
target为一个目标文件,也可以是执行文件
prerequisites是需要生成target所依赖的文件或是目标
command也就是make需要执行的命令(任意的Shell命令)
2、编写Makefile文件
- “prog: main.o sub1.h”
目标:“prog”,这里代表要生成的最终可执行文件。
依赖:“main.o”和“sub1.h”。意味着要成功生成“prog”这个可执行文件,需要有已经编译好的目标文件“main.o”以及头文件“sub1.h”。需要注意的是,虽然这里把头文件列作了依赖,但实际上在后续的编译链接命令中,头文件主要是提供函数声明等信息辅助编译,而不是像目标文件那样直接参与链接生成可执行文件的过程。
命令:“gcc main.o sub1.h -o prog”,此命令指示编译器“gcc”将目标文件“main.o”与头文件“sub1.h”一起进行链接操作(实际上头文件主要起辅助作用,这里准确说是结合目标文件以及头文件所关联的源文件中定义的函数等内容),最终生成名为“prog”的可执行文件。
- “main.o: main.c”
目标:“main.o”,这是要生成的目标文件,通常是对源文件“main.c”进行编译得到的中间产物,后续可用于链接生成可执行文件。
目标:“main.c”,即生成“main.o”的依赖是源文件“main.c”。
命令:“gcc -c main.c”,该命令让编译器“gcc”对源文件“main.c”进行编译操作,“-c”选项表示只进行编译而不进行链接,从而生成目标文件“main.o”。
- “clean:”规则
命令:“rm prog *.o”,用于删除当前目录下名为“prog”的可执行文件以及所有以“.o”结尾的目标文件,达到清理编译过程中生成的可执行文件和中间目标文件的目的,以便后续能进行重新的、干净的编译构建操作。
3、使用Makefile编译及结果
三、总结
这次在Ubuntu系统上编译C语言的实验,我学习使用了gcc直接编译和Makefile进行编译这两种方式;在整个过程中,我深刻的理解到了这两种方式是怎样将C语言编译为可执行文件的。对于 gcc,它作为一个基础的编译工具,在简单场景下表现出色。只需一条简单的命令,就能看到代码变成可执行的形态,这种即时反馈对于学习编程基础和快速验证想法非常有帮助。对于makefile来说,自动化构建,依据依赖关系和修改时间决定重编内容,提高效率。清晰描述项目结构,利于协作。适用于复杂项目。