首页 > 编程语言 >130.hello.c 程序的编译过程

130.hello.c 程序的编译过程

时间:2023-08-02 21:44:08浏览次数:43  
标签:文件 hello 目标 编译 130 链接

130.hello.c 程序的编译过程

以下是一个 hello.c 程序:

#include <stdio.h>

int main()
{
    printf("hello, world\n");
    return 0;
}

在 Unix 系统上,由编译器把源文件转换为目标文件。

gcc -o hello hello.c

这个过程大致如下:

![img](D:\BaiduSyncdisk\C++\笔记图片\130.hello.c 程序的编译过程1.png)

  • 预处理阶段:处理以 # 开头的预处理命令;
  • 编译阶段:翻译成汇编文件;
  • 汇编阶段:将汇编文件翻译成可重定位目标文件;
  • 链接阶段:将可重定位目标文件和 printf.o 等单独预编译好的目标文件进行合并,得到最终的可执行目标文件。

静态链接

静态链接器以一组可重定位目标文件为输入,生成一个完全链接的可执行目标文件作为输出。链接器主要完成以下两个任务:

  • 符号解析:每个符号对应于一个函数、一个全局变量或一个静态变量,符号解析的目的是将每个符号引用与一个符号定义关联起来。
  • 重定位:链接器通过把每个符号定义与一个内存位置关联起来,然后修改所有对这些符号的引用,使得它们指向这个内存位置。

![img](D:\BaiduSyncdisk\C++\笔记图片\130.hello.c 程序的编译过程2.png)

目标文件

  • 可执行目标文件:可以直接在内存中执行;
  • 可重定位目标文件:可与其它可重定位目标文件在链接阶段合并,创建一个可执行目标文件;
  • 共享目标文件:这是一种特殊的可重定位目标文件,可以在运行时被动态加载进内存并链接;

动态链接

静态库有以下两个问题:

  • 当静态库更新时那么整个程序都要重新进行链接;
  • 对于 printf 这种标准函数库,如果每个程序都要有代码,这会极大浪费资源。

共享库是为了解决静态库的这两个问题而设计的,在 Linux 系统中通常用 .so 后缀来表示,Windows 系统上它们被称为 DLL。它具有以下特点:

  • 在给定的文件系统中一个库只有一个文件,所有引用该库的可执行目标文件都共享这个文件,它不会被复制到引用它的可执行文件中;
  • 在内存中,一个共享库的 .text 节(已编译程序的机器代码)的一个副本可以被不同的正在运行的进程共享。

![img](D:\BaiduSyncdisk\C++\笔记图片\130.hello.c 程序的编译过程3.png)

源代码-->预处理-->编译-->优化-->汇编-->链接-->可执行文件

1.预处理

读取c源程序,对其中的伪指令(以#开头的指令)和特殊符号进行处理。包括宏定义替换、条件编译指令、头文件包含指令、特殊符号。 预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。.i预处理后的c文件,.ii预处理后的C++文件。

2.编译阶段

编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。.s文件

3.汇编过程

汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。.o目标文件

4.链接阶段

链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。

参考资料来源:阿秀

标签:文件,hello,目标,编译,130,链接
From: https://www.cnblogs.com/codemagiciant/p/17601838.html

相关文章

  • llvm编译命令与选项
    编译生成可执行文件clanghello.c-ohello编译生成bc文件(不可读)得到LLVM字节码文件.bc(不可读字节码文件)clang-O3-emit-llvmhello.c-c-ohello.bc-O3:表示使用编译优化级别3来编译程序-emit-llvm:表示要通过clang得到LLVM的字节码文件(.bc)或者汇编文件(.ll......
  • tls1.3 可以看到client hello所有内容,还有一半的server hello,是看不到证书issuer、sub
    https://www.cloudshark.org/captures/64d433b1585a 看到tls1.3clienthello内容:SecureSocketsLayerTLSv1.3RecordLayer:HandshakeProtocol:ClientHelloContentType:Handshake(22)Version:TLS1.0(0x0301)Length:234HandshakeProtocol:ClientHelloHandshak......
  • C语言逆向——预处理之宏定义、条件编译与文件包含
    预处理之宏定义、条件编译与文件包含预处理一般是指在程序源代码被转换为二进制代码之前,由预处理器对程序源代码文本进行处理,处理后的结果再由编译器进一步编译。预处理功能主要包括宏定义、文件包含、条件编译三部分。宏定义简单的宏:#define标识符字符序列#defineFALSE0#d......
  • C语言逆向——数组和结构体,数组多维只是一个编译构造的假象,本质会转成一维数组,结构体
    数组数组是C语言中非常重要的一个概念,学习C语言主要就是两个知识点:数组、指针,学好这两个,那么你的C语言一定也会很好。什么是数组?或者说什么情况下我们需要使用数组,比如说我们需要定义一个人的年龄,我们可以定义一个变量来表示,但是如果我们需要定义三个人的年龄呢?那就需要三个变量来......
  • 当编译器没有SetProcessDpiAwareness()这个函数时...
    #include<Shlobj.h>intsetdpi(){//定义一个函数指针类型typedefHRESULT(WINAPI*SetProcessDpiAwarenessFunc)(intvalue);//加载Shcore.dllHMODULEhModule=LoadLibrary("Shcore.dll");if(hModule==NULL){//加载失败......
  • live555交叉编译
    一、下载live555源码源码下载路劲为:http://www.live555.com/liveMedia/二、交叉编译下面以aarch64-linux-gnu编译器为例说明交叉编译方法2.1不编译openssl由于live555里面默认使用到openssl,需要先编译openssl,比较麻烦,可以配置不编译进去openssl.1、复制con......
  • 编译器、链接器和解释器
    编译器编译器的作用就是将高级编程语言翻译为机器代码。编译器工作过程一般分为:词法分析:将高级语言解析成Token集合;语法分析:将Token集合构建成语法树,在这个过程可以判断出语法是否有误,比如while后面是否{等等;语义分析:判断语法树是否有明显的语义错处,比如:string不能......
  • java 查看class文件的jdk版本的两种方式(编译版本)
    1.情景展示有时候我们需要知道jar包里面class文件的jdk编译版本,来排查错误。以上图为例,如何实现?2.具体分析将其中一个class文件解压出来,然后查看大致的jdk版本号。3.解决方案使用解压工具打开gridreport.jar,将Report.class解压到桌面。方式一:使用文本编辑工具EditPlus......
  • 安卓项目编译RocketX集成流程
    依赖gradle插件//appmodule的build.gradle加入applyplugin:'com.rocketx'//注:保证写入依赖关系在最后一行 //在根目录的build.gradle加入buildscript{dependencies{classpath'io.github.trycatchx:rocketx:1.1.......
  • ubuntu16.04编译安装nginx1.24.0
    环境:DistributorID: UbuntuDescription: Ubuntu16.04.7LTSRelease: 16.04Codename: xenial 安装包:pcre-8.45.tar.gznginx-1.24.0.tar.gz开始安装:安装pcretar-xzvfpcre-8.45.tar.gzcdpcre-8.45./configure--prefix=/usr/local/pcremake&&makeinstall......