1. 主页
  2. 文档
  3. C语言教程
  4. C语言基础教程
  5. 编译 C 程序:- 幕后

编译 C 程序:- 幕后

C 是一种中级语言,它需要一个编译器将其转换为可执行代码,以便程序可以在我们的机器上运行。 

我们如何编译和运行 C 程序?
以下是我们在带有 gcc 编译器的 Ubuntu 机器上使用的步骤。  

  • 我们首先使用编辑器创建一个 C 程序并将文件保存为 filename.c
 $ ./filename 
  • 上图显示了一个将两个数字相加的简单程序。

  • 然后使用下面的命令编译它。
 $ gcc -Wall filename.c –o filename
  • 选项 -Wall 启用所有编译器的警告消息。建议使用此选项以生成更好的代码。 
    选项 -o 用于指定输出文件名。如果我们不使用此选项,则会生成一个名为 a.out 的输出文件。

  • 生成编译可执行文件后,我们使用以下命令运行生成的可执行文件。

编译过程中发生了什么?
编译器将 C 程序转换为可执行文件。C 程序成为可执行文件有四个阶段: 

  1. 预处理
  2. 汇编
  3. 部件
  4. 链接

通过执行以下命令,我们可以获得当前目录中的所有中间文件以及可执行文件。

 $gcc -Wall -save-temps filename.c –o filename 

以下屏幕截图显示了所有生成的中间文件。 

让我们一一看看这些中间文件包含什么。 

预处理

这是传递源代码的第一个阶段。这个阶段包括:  

  • 删除注释
  • 宏的扩展
  • 扩展包含的文件。
  • 条件编译

预处理后的输出存储在filename.i 中。让我们看看 filename.i 里面有什么: 使用$vi filename.i
在上面的输出中,源文件充满了大量的信息,但最后我们的代码被保留了。 
分析:

  • printf 现在包含 a + b 而不是 add(a, b) 这是因为宏已经扩展。
  • 评论被删除。
  • #include<stdio.h>不见了,而是我们看到了很多代码。所以头文件已经被扩展并包含在我们的源文件中。

编译

下一步是编译 filename.i 并生成一个;中间编译输出文件filename.s。该文件在汇编级指令中。让我们使用$vi filename.s 来查看这个文件

快照显示它是汇编语言,汇编程序可以理解。 

汇编
在这个阶段,filename.s 被作为输入并被汇编器转换成filename.o。该文件包含机器级指令。在此阶段,仅将现有代码转换为机器语言,不解析 printf() 等函数调用。让我们使用$vi filename.o查看这个文件

链接

这是完成函数调用与其定义的所有链接的最后阶段。链接器知道所有这些功能在哪里实现。链接器也做了一些额外的工作,它向我们的程序添加了一些额外的代码,这是程序启动和结束时需要的。例如,设置环境所需的代码(例如传递命令行参数)。使用$size filename.o$size filename可以轻松验证此任务。通过这些命令,我​​们知道输出文件是如何从目标文件增加到可执行文件的。这是因为链接器在我们的程序中添加了额外的代码。 

注意 GCC 默认做动态链接,所以 printf() 在上面的程序中是动态链接的。

 

 

这篇文章对您有用吗?