欢迎光临
我们一直在努力

c语言的翻译与执行

  

目录

  

前言

一、总体过程

1.1 翻译

1.2 执行

二、问题归纳

question1:调试问题种类与过程的对应?

question2:为什么是int main(),为什么是return 0?

question3:#include和extern的区别

question4:主要的编译器包括哪些?

三、简单总结

前言

        在学习c语言的过程中,总是会听到配环境,编译器等词语,而且在编程过程中,除了我们的源文件和最终的可执行程序,中间还会产生一个后缀为.obj的中间文件。于是我们会产生这样的疑问,源文件到可执行程序到底经历了哪些过程,所谓的“环境”和“编辑器”在这个过程中起到什么作用,中间是否还产生了其他文件?下面我们来简单剖析一下c语言中的翻译过程。

一、总体过程

        学习完之后,我画出了几个逻辑图,用来展示总体的过程

        从写出“hello world”到黑色窗口(标准输出)总的经历了两个大的过程:翻译和执行

1.1 翻译

        翻译过程将c语言代码处理成二进制序列(这时候我们可以想到,二进制序列实际上就是高低电平,映射到硬件实现的话)

        具体的翻译过程又包括“编译”和“链接”过程(这是我们耳熟能详的)。大概过程就是思维导图里面的,编译过程包括3个阶段,分别是:

        1.预处理(预编译):此阶段主要就是整理c语言文本(其实个人感觉c语言还是比较容易理解的,编程语言都比较顶层,主要还是面向人类的),这个“整理”就包括执行预处理指令和忽略注释,生成的一般就是.i文件。

        2.编译:此阶段的话就将c语言代码转换成了汇编代码,主要过程就是语法分析,语义分析,词法分析和符号汇总。

        3.汇编:此阶段就是将汇编代码转化成二进制指令,同时形成符号表。

        值得注意的是,在链接过程之前,各个文件的编译时独立的,彼此不知道彼此的存在,也就是说每个.c文件各自都会形成一个符号表。

        对于链接过程,主要就是合并符号表和合成段表。

        然后中间文件的转化和对应阶段可以看下图。

1.2 执行

        再细看一下执行过程,可以看到先是进入main函数,也就是我们以前说的程序入口。

(执行的第一步是将程序写入内存,写过单片机的同志可能都有过烧板子的经历,本质上就是手动将程序输入内存)

二、问题归纳

question1:调试问题种类与过程的对应?

        1.编译错误:编译过程中产生

        2.链接错误:链接过程中产生

        3.执行错误:执行过程中产生

question2:为什么是int main(),为什么是return 0?

        首先在c语言中约定的就是,程序成功退出就返回0(宏:#define EXIT_SUCCES 0);失败退出就返回1(#define EXIT_FAILURE 1),return 0放在主程序末尾,如果程序正常执行完就会返回0,实际上也就是向编程者提供正常执行的信息。

        主函数本质上也是函数,返回值为整型,所以前面就是int。

question3:#include和extern的区别

维度

#include

extern

阶段

预处理阶段(编译前)

编译阶段(实际是编译时的声明,影响链接)

作用

将头文件内容插入当前文件

声明符号在其他文件中定义

处理对象

文件内容(通常是声明、宏、类型)

标识符(变量、函数)

本质上来讲:

        #include是预处理指令,用于文本包含,解决“有什么可以用”的问题。

        extern是关键字,用于跨文件声明,解决“定义在哪”的问题。

        #include和extern通过接口与实现分离、跨文件符号共享,让C语言具备了构建大型程序的能力。

根据我的小练习经验,一般模块化编程的文件结构就是:

        main.c:逻辑层,写整个项目的逻辑框架(同时又是程序执行的出入口)。

        function.h:连接层,声明具体的功能函数,自定义宏以及结构体。

        function.c:实现层,定义具体的功能函数。

question4:主要的编译器包括哪些?

编译器

主导者/社区

核心特点

主要用武之地

对应的链接器

GCC(GNU Compiler Collection)

GNU开源社区

开源世界的元老,支持平台最广,优化成熟,是Linux系统的默认编译器。

Linux、嵌入式系统、Unix-like系统

ld(GNU Binutils的一部分)

Clang

LLVM社区 (苹果主导)

编译速度快,内存占用小,报错信息极其清晰友好,被苹果选为macOS的默认编译器。

macOS、iOS、性能敏感的大型项目

LLVM lld(或系统默认的ld)

MSVC(Microsoft Visual C++)

微软

Windows平台的王者,与Visual Studio IDE深度集成,调试工具强大,原生支持Windows API。

Windows桌面应用、游戏开发

link.exe(集成在Visual Studio中)

        也就是说,visual studio中编译器实际上是MSVC(Microsoft Visual C++),而Linux默认就是gcc的编译器。我们常说的配置环境也就是配置编译器和连接器的过程。(vs code我记得一般配置的是gcc的编译器)。  

三、简单总结

        这样我们就可以解释,在初学c语言中为什么总是打出经典的初始框架,#include<stdio.h>包含标准的输入输出库,让我们可以使用scanf和printf等基本的输入输出函数;主函数也就是初始化环境后进入的第一个函数,然后从主函数的第一行顺序往后执行,直到顺利结束后结尾返回0。(也许程序的生命周期就是主函数的第一行到return 0,中间经历很多的语句,进出很多的函数,跨越很多的文件)。

赞(0)
未经允许不得转载:171主机测评 » c语言的翻译与执行
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址