栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

一个简单的C语言程序是怎么来的呢?

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

一个简单的C语言程序是怎么来的呢?

1.定义程序的目标

        首先构思这个C程序的作用,干什么,比如我想打印“hello world!”

2.设计程序:

        进行简单的程序设计,比如我们需要设计一个打印hello word的C语言程序,需要打印函数。不同的程序有不同的设计方案,在c语言程序设计中讲了很多。

3.编写代码:

        编辑是通过编辑器,实现C语言代码的编写,即编辑器提供了编写C语言代码的平台;

        比如:

我们定义头文件 headtest.h:

#include 

编写C文件 Untitled-1.c:

#include "headtest.h"
 
int main()
{
    
    printf("Hello, World! n");
 
    return 0;
}

就会生成:

       

        在编辑好代码之后,会生成对应的.c文件和.h文件。

输入命令:  gcc Untitled-1.c -o hello 程序进入C程序的编程通道,输出hello.exe

        一个典型的C程序编译管道,包含预处理、编译、汇编、链接四个环节。

4.预处理

GCC 在第一个阶段会调用预处理器 cpp 来对 C 源程序进行预处理

预处理一般有三个作用:宏定义,文件包含,条件编译。
        I.宏定义简单的来说就是”#define …”,就是将程序中的某个常量全部替换成某个数据;
        II.文件包含简单的来说就是”#include …”,就是在文件目录中找到include后的头文件;
        III.条件编译指该程序要符合某个条件才运行,否则不运行。

也就是说,我们一般可以简单理解为:以井号’#’开头的 语句就是预处理指令。这些指令会在预处理的时候解释,拷贝对应的文件来覆盖#语句。在预处理的时候GCC还会删除注释。

我们可以通过命令:gcc Untitled-1.c -o hello.i -E 来获取这个预处理之后的文件,就是.i 文件。

打开大概看看里面吧:

处理之后引入了很多包

主程序也没有了注释。

5.编译

        将经过预处理之后生成的.i 文件进一步的翻译,它包括词法和语法的分析, 最终生成对应硬件平台的汇编语言,具体生成什么平台 的汇编文件取决于所采用的编译器,如果用的是 GCC,那么将会生成 x86 格式的汇编文件,如果用的是针对 ARM 平台的交叉编译器,那么将会生成 ARM 格式的汇编文件。

        也就是将C语言这种高级语言编译成汇编语言,不同的编译器会有不同格式的汇编文件。

我们可以通过命令:gcc hello.i -o hello.s -S 来获取这个编译好的文件,也就是.s文件。

 打开简单看看:

 代码变得精简短小,不再是看得懂的C语言了

6.汇编

        编译器 gcc 调用汇编器 as 将汇编源程序翻译成 为可重定位文件。汇编指令跟处理器直接运行的二进制指令流之间基本是一一对应的关系, 该阶段只将.s 文件里面的汇编翻译成相应的指令。

        我们拿到了编译成汇编语言的.s文件,接下来就是进一步的翻译,也就是变成计算机可以看得懂的指令

 我们可以通过命令:gcc hello.s -o hello.o -c  获得汇编后的文件,也就是.o文件。

 打开简单看看:

 emmmmm看不懂了

 根据说明:

        .o 文件是一个 ELF 格式的可重定位(relocatable)文件,所谓的可重定位,指的是该文件虽 然已经包含可以让处理器直接运行的指令流,但是程序中的所有的全局符号尚未定位,所谓 的全局符号,就是指函数和全局变量,函数和全局变量默认情况下是可以被外部文件引用的, 由于定义和调用可以出现在不同的文件当中,因此他们在编译的过程中需要确定其入口地 址,比如 a.c 文件里面定义了一个函数 func( ),b.c 文件里面调用了该函数,那么在完成第 三阶段汇编之后,b.o 文件里面的函数 func( )的地址将是 0,显然这是不能运行的,必须要 找到 a.c 文件里面函数 func( )的确切的入口地址,然后将 b.c 中的“全局符号”func 重新定 位为这个地址,程序才能正确运行。

        那么定位这个地址,就是下一个阶段,连接:

7.连接

链接系统的标准 C 库、gcc 内置库等基本库文件。

使用命令:gcc hello.o -o Untitled-1 -lc -lgcc  链接生成可执行文件,-lc 和-lgcc 是默认的,可以省略。

根据说明:

  链接还会合并相同权限的段(section)。一个可执行镜像文件可以由多个可重定位文件链接而成,比如 a.o,b.o,c.o 这三个可重定位文件链接生成一个叫 做 x 的可执行文件( ELF 格式)ELF 格式是符合一定规范的文件格式,里面包含很多段(section),其中.text 段存放了运行代码,.data 段里面存放了已经初始化了的全局变量和静态局部变量,.rodata 段存放了程序中所有的常量等等,除了这些程序运行时需要用得到的代码和数据之外,还有一些是程序在 从磁盘加载到内存时需要提供给加载器的辅助信息,比如提供代码重定位信息的.rel.text 段, ELF 格式文件中的符号表.symtab 段等,这些信息将会在程序加载完毕之后被丢弃,而不会 存在于程序运行的内存当中。将多个不同的可重定位 ELF 格式文件链接成一个可执行 ELF 格式文件的过程中,会将它们不同的各个段按照“执行视图”合并起来,简言之,就是将具有相同权限的段合并到一起,比如各个文件中的具有只读权限的.text 段和.rodata 段将会被合并到一起,当程序有多个执行实例(多个进程)时,这些 执行实例会共享一个只读段的副本,从而节省内存空间。

也就是在经过连接过后,我们就可以通过可执行文件实现我们的设计了。

执行文件:

 总结

        这就是一个C程序从构思到实现的一个简单实现过程,其中我们创建了几个文件:

        

 由此我们可以总结一下:

        .h文件就是头文件,里面包含的几乎是预处理要处理的信息。

        .c文件就是我们写的C语言的结构体,函数等。

        .i文件是执行预处理之后的文件。

        .s文件是翻译之后的汇编语言文件。

        .o文件是会变后的可重定位指令文件。

        .exe文件就是最终的可执行文件。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/529282.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号