当前位置: 首页 > news >正文

C语言初识编译和链接

目录

  • 翻译环境和运行环境
  • 编译环境
    • 预编译
    • 编译
      • 词法分析
      • 语法分析
      • 语义分析
    • 汇编
  • 链接
  • 运行环境

翻译环境和运行环境

在ANSI C的任何⼀种实现中,存在两个不同的环境。
第1种是翻译环境,在这个环境中源代码被转换为可执⾏的机器指令(⼆进制指令)。
第2种是执⾏环境,它⽤于实际执⾏代码。
在这里插入图片描述

编译环境

翻译环境又分为两个,分别是编译环境和链接环境。
⽽编译⼜可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。
在这里插入图片描述
⼀个C语⾔的项⽬中可能有多个 .c ⽂件⼀起构建,那多个 .c ⽂件如何⽣成可执⾏程序呢?
• 多个.c⽂件单独经过编译器,编译处理⽣成对应的⽬标⽂件。
• 注:在Windows环境下的⽬标⽂件的后缀是 .obj ,Linux环境下⽬标⽂件的后缀是 .o
• 多个⽬标⽂件和链接库⼀起经过链接器处理⽣成最终的可执⾏程序。
• 链接库是指运⾏时库(它是⽀持程序运⾏的基本函数集合)或者第三⽅库。
具体的流程可以参考下图。
在这里插入图片描述

预编译

在预处理阶段,源⽂件和头⽂件会被处理成为 .i 为后缀的⽂件。
在 gcc 环境下想观察⼀下,对 test.c ⽂件预处理后的.i⽂件,命令如下:

gcc -E test.c -o test.i

预处理阶段主要处理那些源⽂件中#开始的预编译指令。⽐如:#include,#define,处理的规则如下:
• 将所有的 #define 删除,并展开所有的宏定义。
• 处理所有的条件编译指令,如: #if、#ifdef、#elif、#else、#endif 。
• 处理#include 预编译指令,将包含的头文件的内容插⼊到该预编译指令的位置。这个过程是递归进行的,也就是说被包含的头文件件也可能包含其他文件。
• 删除所有的注释
• 添加行号和文件名标识,方便后续编译器生成调试信息等。
• 或保留所有的#pragma的编译器指令,编译器后续会使用。
经过预处理后的 .i ⽂件中不再包含宏定义,因为宏已经被展开。并且包含的头⽂件都被插⼊到 .i⽂件中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的 .i 文件来确认。
例如:

#include<stdio.h>
//呵呵
#define M 100;
int main()
{int x = 0;x = M;return 0;
}

预编译后:
上面那些#代表的是头文件编译后的内容,因条件有限,没法给各位具体呈现一下了。

###########
###########
###########
###########
###########
###########
###########
###########int main()
{int x = 0;x = 100;return 0;
}

这里将那行注释删除,留下了一行空格,然后“x=M”中的M也由100直接替换。

编译

编译过程就是将预处理后的⽂件进⾏⼀系列的:词法分析、语法分析、语义分析及优化,⽣成相应的汇编代码文件。
编译命令如下:

gcc -S test.i -o test.s

举个例子来分析一下:
对下面这句代码进行编译。

array[index] = (index+4)*(2+6);

词法分析

将源代码程序被输⼊扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成⼀系列的记号(关键字、标识符、字面量、特殊字符等)。
上⾯程序进⾏词法分析后得到了16个记号:
在这里插入图片描述

语法分析

接下来语法分析器,将对扫描产⽣的记号进⾏语法分析,从而产⽣语法树。这些语法树是以表达式为节点的树。
在这里插入图片描述

语义分析

由语义分析器来完成语义分析,即对表达式的语法层⾯分析。编译器所能做的分析是语义的静态分析。静态语义分析通常包括声明和类型的匹配,类型的转换等。这个阶段会报告错误的语法信息。

array[index] = (index+4)*(2+6);

在这里插入图片描述

汇编

汇编器是将汇编代码转转变成机器可执⾏的指令,每⼀个汇编语句几乎都对应⼀条机器指令。就是根据汇编指令和机器指令的对照表⼀⼀的进⾏翻译,也不做指令优化。
汇编的命令如下:

gcc -c test.s -o test.o

链接

链接是⼀个复杂的过程,链接的时候需要把⼀堆文件链接在⼀起才生成可执⾏程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是⼀个项目中多文件、多模块之间互相调用的问题。
比如:
在⼀个C的项⽬中有2个.c⽂件( test.c 和 add.c ),代码如下:
add.c

int g_val = 2022;
int Add(int x, int y)
{return x+y;
}

test.c

#include <stdio.h>
//test.c
//声明外部函数
extern int Add(int x, int y);
//声明外部的全局变量
extern int g_val;
int main()
{int a = 10;int b = 20;int sum = Add(a, b);printf("%d\n", sum);return 0;
}

我们已经知道,每个源文件都是单独经过编译器处理生成对应的目标文件。
test.c 经过编译器处理生成 test.o
add.c 经过编译器处理生成 add.o
我们在 test.c 的文件中使用了 add.c 文件中的 Add 函数和 g_val 变量。
我们在 test.c 文件中每⼀次使用 Add 函数和 g_val 的时候必须确切的知道 Add 和 g_val 的地址,但是由于每个⽂件是单独编译的,在编译器编译 test.c 的时候并不知道 Add 函数和 g_val变量的地址,所以暂时把调⽤ Add 的指令的⽬标地址和 g_val 的地址搁置。即(Add的地址暂存为空地址):

ADD=0x0000

等待最后链接的时候由链接器根据引用的符号 Add 在其他模块中查找 Add 函数的地址,然后将 test.c 中所有引用到Add 的指令重新修正(相当于重新给Add的地址赋值),让他们的目标地址为真正的 Add 函数的地址,对于全局变量 g_val 也是类似的方法来修正地址。这个地址修正的过程也被叫做:重定位。

运行环境

  1. 程序必须载⼊内存中。在有操作系统的环境中:⼀般这个由操作系统完成。在独⽴的环境中,程序的载⼊必须由手工安排,也可能是通过可执⾏代码置⼊只读内存来完成。(比如嵌入式)
  2. 程序的执行便开始。接着便调⽤main函数。
  3. 开始执行程序代码。这个时候程序将使⽤⼀个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执⾏过程⼀直保留他们的值。
  4. 终止程序。正常终止main函数;也有可能是意外终止。

本次介绍就结束了,因为条件限制,有的并没由给大家编译呈现出来,给大家带来的不好的体验,对此很抱歉。
同时也感谢各位的观看,如有错误请在评论区指正,共勉。

相关文章:

C语言初识编译和链接

目录 翻译环境和运行环境编译环境预编译编译词法分析语法分析语义分析 汇编 链接运行环境 翻译环境和运行环境 在ANSI C的任何⼀种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个环境中源代码被转换为可执⾏的机器指令&#xff08;⼆进制指令&…...

TrinityCore环境搭建

1)https://192.168.3.96:41797/soft/app root jianan2)mysql322bb8f85b0920d9 192.168.3.96 9f5c813fefbbc3aa3) su wow cd /home/wow/TrinityCore/TrinityCore-TDB335.22061/build cmake ../ -DCMAKE_INSTALL_PREFIX/home/wow/server3.5.5 #构建项目cmake ../ -DCMAKE_INSTALL…...

Proteus 仿真设计:开启电子工程创新之门

摘要&#xff1a; 本文详细介绍了 Proteus 仿真软件在电子工程领域的广泛应用。从 Proteus 的功能特点、安装与使用方法入手&#xff0c;深入探讨了其在电路设计、单片机系统仿真、PCB 设计等方面的强大优势。通过具体的案例分析&#xff0c;展示了如何利用 Proteus 进行高效的…...

microchip dspic3一些奇怪问题

UART初始化&#xff0c;导致一些MCU PIN输出低电平。 https://microchip.my.site.com/s/case/500V4000007jvz4IAA/detail 板子上电EEPROM读取不稳定&#xff0c;增加延时解决问题。 –If delay 1ms, will read EE Err –If delay 10ms, program and reset, will read EE err.…...

FinOps原则:云计算成本管理的关键

导语&#xff1a; FinOps 原则为我们提供了北极星&#xff08;North Star&#xff09;&#xff0c;在我们实践云财务管理时指导我们的活动。这些原则由 FinOps 基金会成员制定&#xff0c;并通过经验磨练出来。 北极星&#xff08;North Star&#xff09;的含义&#xff1a; …...

JavaScript之如何优化模板字符串的性能

在 JavaScript 中&#xff0c;优化模板字符串的性能可以从几个方面入手。模板字符串&#xff08;Template Literals&#xff09;是 ES6 引入的特性&#xff0c;它们使用反引号 () 包围&#xff0c;可以嵌入表达式并支持多行字符串。虽然模板字符串通常很方便&#xff0c;但在性…...

不能将类型“null”分配给类型“number | undefined”。ts(2322)

错误解释&#xff1a; 这个TypeScript错误表明你正在尝试将null赋值给一个预期为number类型或undefined类型的变量。在TypeScript中&#xff0c;null和undefined是有效的值&#xff0c;但通常我们希望它们与number类型不兼容。 解决方法&#xff1a; 检查导致错误的赋值语句&…...

Nginx部署前端Vue项目详细教程

文章目录 Nginx部署前端Vue项目详细教程准备工作打包Vue项目安装Nginx配置Nginx创建配置文件启用配置文件 部署Vue项目配置SSL&#xff08;可选&#xff09;测试和验证总结 Nginx部署前端Vue项目详细教程 本教程将详细介绍如何使用Nginx部署前端Vue项目&#xff0c;涵盖从项目…...

kvm 虚拟机命令行虚拟机操作、制作快照和恢复快照以及工作常用总结

文章目录 kvm 虚拟机命令行虚拟机操作、制作快照和恢复快照一、kvm 虚拟机命令行虚拟机操作(创建和删除)查看虚拟机virt-install创建一个虚拟机关闭虚拟机重启虚拟机销毁虚拟机 二、kvm 制作快照和恢复快照**创建快照**工作常见问题创建快照报错&#xff1a;&#xff1a;intern…...

内网安全-横向移动【3】

1.域横向移动-内网服务-Exchange探针 Exchange是一个电子右键服务组件&#xff0c;由微软公司开发。它不仅是一个邮件系统&#xff0c;还是一个消息与协作系统。Exchange可以用来构建企业、学校的邮件系统&#xff0c;同时也是一个协作平台&#xff0c;可以基于此开发工作流、…...

语言中的浮点数

浮点数相比定点数或者整数&#xff0c;为了处理小数点引入了指数&#xff0c;导致小数点的位置根据不同浮点数而不同&#xff0c;故名为Floating Point Number. 一般而言&#xff0c;IEEE754标准被大部分编程语言的浮点数使用&#xff0c;它节省了浮点数的保存空间。如不然&…...

Pyspark下操作dataframe方法(1)

文章目录 Pyspark dataframe创建DataFrame使用Row对象使用元组与scheam使用字典与scheam注意 agg 聚合操作alias 设置别名字段设置别名设置dataframe别名 cache 缓存checkpoint RDD持久化到外部存储coalesce 设置dataframe分区数量collect 拉取数据columns 获取dataframe列 Pys…...

注解实现json序列化的时候自动进行数据脱敏

最近在进行开发的时候遇到一个问题&#xff0c;需要对用户信息进行脱敏处理&#xff0c;原有的方式是写一个util类&#xff0c;在需要脱敏的字段查出数据后&#xff0c;显示掉用方法处理后再set回去&#xff0c;觉得这种方式能实现功能&#xff0c;但是不是特别优雅&#xff0c…...

使用Python下载文件的简易指南

在日常的数据处理、自动化任务或软件开发中&#xff0c;经常需要从网络上下载文件。Python作为一门功能强大的编程语言&#xff0c;提供了多种方法来实现文件的下载。本文将介绍几种常用的方法来使用Python下载文件&#xff0c;包括使用requests库和urllib库。 准备工作 在开…...

中秋国庆双节长假,景区迎来客流高峰,如何保障景区安全管理?

一、方案背景 近年来&#xff0c;国内旅游市场持续升温&#xff0c;节假日期间景区游客数量激增&#xff0c;给景区安全管理带来了巨大挑战。然而&#xff0c;景区安全风险意识不足、防护措施不完善、游客安全意识欠缺等问题依然存在&#xff0c;导致景区安全事故频发。随着中秋…...

多维数组转一维数组:探索 JavaScript 中的数组扁平化

在 JavaScript 编程中&#xff0c;我们经常会遇到需要将多维数组转换为一维数组的情况。无论是处理复杂的数据结构还是进行数据的进一步操作&#xff0c;数组扁平化都是一个常见且有用的技术。本文将介绍几种在 JavaScript 中将多维数组转换为一维数组的方法。 什么是数组扁平…...

配环境时的一些记录

连centos&#xff1a;正常连就好&#xff08;密码验证码&#xff09;连rocky&#xff1a;需要在centos上连&#xff0c;终端里直接ssh [rocky_ip]&#xff1b;在vscode中需要&#xff1a; 修改配置文件&#xff1a;打开命令面板&#xff08;ctrlshiftp&#xff09; -> 输入并…...

如何解析域名到网站?

在现代互联网中&#xff0c;域名解析是用户访问网站的关键过程。用户通过输入易于记忆的域名来访问网站&#xff0c;而背后则是复杂的域名解析机制将域名转换为服务器的IP地址&#xff0c;使得浏览器能够找到并加载目标网站。聚名网详细介绍域名解析的过程及其相关技术。 一、…...

【F172】基于Springboot+vue实现的智能菜谱系统

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 项目描述 近些年&#xff0c;随着中国经济发展&#xff0c;人民的…...

Spring-AOP核心源码、原理详解前篇

本文主要分4部分 Aop原理介绍介绍aop相关的一些类通过源码详解aop代理的创建过程通过源码详解aop代理的调用过程Aop代理一些特性的使用案例 Spring AOP原理 原理比较简单&#xff0c;主要就是使用jdk动态代理和cglib代理来创建代理对象&#xff0c;通过代理对象来访问目标对象…...

EFFACT架构:全同态加密硬件加速的创新设计

1. EFFACT架构概述&#xff1a;当硬件设计遇上全同态加密在密码学加速器的世界里&#xff0c;我们一直在寻找一个平衡点——如何在有限的芯片面积和功耗预算下&#xff0c;处理那些看似无解的复杂计算&#xff1f;EFFACT架构的诞生&#xff0c;正是为了解决全同态加密&#xff…...

【开源】基于 ASP.NET Core Blazor Server 10.0 构建的学生信息查询系统

学生查询系统基于 ASP.NET Core Blazor Server 10.0 构建的学生信息查询系统&#xff0c;使用 Excel 文件作为数据源&#xff0c;支持动态列适配和响应式布局。功能特性灵活查询&#xff1a;支持按姓名、学号进行模糊查询&#xff0c;可单独或组合使用动态列适配&#xff1a;不…...

从编译失败到成功发布:用VS BuildTools彻底解决MSBuild“能编译不能发布”的坑

从编译到发布&#xff1a;彻底解决MSBuild部署.NET Framework网站的技术困境 许多.NET开发者都曾遇到过这样的场景&#xff1a;在命令行中能够顺利编译项目&#xff0c;却在尝试发布&#xff08;Publish&#xff09;ASP.NET网站时遭遇各种莫名错误。这种"能编译不能发布&q…...

从 API 密钥管理角度看 Taotoken 控制台提供的安全与便捷性

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 从 API 密钥管理角度看 Taotoken 控制台提供的安全与便捷性 1. 引言&#xff1a;集中管理的起点 在开发涉及大模型的应用时&#…...

别再手动算矩阵了!CloudCompare 2025版点云变换保姆级教程(齐次/欧拉/轴角一键搞定)

别再手动算矩阵了&#xff01;CloudCompare 2025版点云变换保姆级教程&#xff08;齐次/欧拉/轴角一键搞定&#xff09; 点云数据处理中&#xff0c;最让人头疼的莫过于各种空间变换操作。传统方法需要手动计算变换矩阵&#xff0c;不仅容易出错&#xff0c;还耗费大量时间。Cl…...

Dell R730 2U服务器实战:解锁Nvidia P4计算卡在虚拟化环境下的AI训练潜能

1. 硬件准备与安装避坑指南 Dell PowerEdge R730作为一款经典的2U机架式服务器&#xff0c;在二手市场上性价比极高。我最近给实验室淘了两台二手R730&#xff0c;准备搭建AI训练集群。这次重点分享如何在这台服务器上安装Nvidia Tesla P4计算卡的经验。 先说说为什么选P4这张卡…...

基于GitHub Actions的跨平台应用自动化发布流水线实战指南

1. 项目概述&#xff1a;一个开源应用发布管道的诞生在软件开发的日常里&#xff0c;发布环节常常是那个“说起来简单&#xff0c;做起来一团糟”的部分。尤其是在团队协作中&#xff0c;从代码提交到最终用户能下载到安装包&#xff0c;中间要经历构建、测试、签名、打包、上传…...

GCC __builtin函数避坑指南:让你的跨平台C代码在ARM和x86上都跑得稳

GCC __builtin函数跨平台避坑实战&#xff1a;ARM与x86兼容性深度解析 在嵌入式开发与高性能计算领域&#xff0c;GCC编译器的__builtin函数集一直是开发者提升性能的利器。但当代码需要同时运行在ARM架构的嵌入式设备和x86架构的服务器上时&#xff0c;这些看似美妙的"魔…...

C++ 列表初始化容器

initializer_list是一个模板类&#xff0c;可能你已经用过它了但不知道而已&#xff0c;比如下面的代码就用了 #include <iostream> #include <vector>int main() {std::vector<int> vc({ 1,2,3,4 }); //这里调用了构造函数&#xff0c;实参为{1,2,3,4}ret…...

AI——Dify高级RAG优化

高级RAG优化简介一、基础RAG的核心痛点二、全流程高级优化技术&#xff08;一&#xff09;索引构建阶段&#xff1a;高质量数据底座&#xff08;二&#xff09;检索阶段&#xff1a;精准召回与重排&#xff08;三&#xff09;检索后阶段&#xff1a;上下文压缩与提纯&#xff0…...