C--编译和链接见解

欢迎各位看官!如果您觉得这篇文章对您有帮助的话
欢迎您分享给更多人哦 感谢大家的点赞收藏评论

感谢各位看官的支持!!!请添加图片描述

一:翻译环境和运行环境

  在ANSIIC的任何一种实现中,存在两个不同的环境
  1,翻译环境:源代码 被转换成 可执行的机器指令(二进制指令) (电脑只能读懂这个)
  2,执行环境:实际执行代码
  其实翻译环境是由编译和链接两个⼤的过程组成的,⽽编译⼜可以分解成:预处理(有些书也叫预编
译)、编译、汇编三个过程

在这里插入图片描述

二.预处理(预编译),编译和汇编

2.1:预处理(预编译)

在预处理阶段。**源文件和头文件**都会被处理成后缀为(.i)的文件

```c
命令:gcc -E test.c -o test.i **(-E到预处理结束,-o,生成test.i文件)**
> 1.预处理阶段主要处理那些源⽂件中#开始的预编译指令。
⽐如:#include,#define,处理的规则如下: 
> • 将所有的 #define 删除,并展开所有的宏定义。**(将#define定义的内容展开) 
> • 处理所有的条件编译指令,如: #if、#ifdef、#elif、#else、#endif 。
> • 处理#include 预编译指令,将包含的头⽂件的内容插⼊到该预编译指令的位置。
这个过程是递归进行的,也就是说被包含的头⽂件也可能包含其他⽂件。**
> • 删除所有的注释(变成空格) • 添加行号和文件名标识,方便后续编译器生成调试信息等。
>  • 或保留所有的#pragma的编译器指令,编译器后续会使用。

经过预处理后的 .i 文件中不再包含宏定义,因为宏已经被展开。并且包含的头文件呢都被插入到 .i文件中。所以当我们无法知道宏定义或者头文件是否包含正确的时候,可以查看预处理后的 .i 文件来确认。

2.2编译

词法分析,语法分析,语义分析。将C语言代码转换成汇编代码

gcc -S test.i -o test.s //生成test.s
例如: arr[index]=(index+4)*(2+6)

在这里插入图片描述

2.3 汇编

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

gcc -c test.s -o test.o
对test.c处理成test.o(二进制文件)

链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执行程序。
链接过程主要包括:地址和空间分配符号决议重定位等这些步骤。
链接解决的是⼀个项⽬中多⽂件、多模块之间互相调用的问题
在这里插入图片描述

三.运行环境

  1. 程序必须载入内存中。在有操作系统的环境中:⼀般这个由操作系统完成。在独立的环境中(单片机,里面无操作系统),程序的载入必须手工安排,也可能是通过可执行代码置入只读内存来完成。
    3. 程序的执行便开始。接着便调用main函数。
    4. 开始执⾏程序代码。这个时候程序将使⽤⼀个运⾏时堆栈(函数栈帧)(stack),存储函数的局部变量和返回地址程序是由一个个函数组成的,每创建一个函数就会创建一个运行时堆栈,运行时维护,结束时销毁)程序同时也可以使⽤静态(static)内存,存储于静态内存中的变量在程序的整个执行过程⼀直保留他们的值。
    5. 终止程序。正常终止main函数;也有可能是意外终止。
    在这里插入图片描述

四.预处理详解

1.1define 定义常量

__FILE__ //进⾏编译的源⽂件
__LINE__ //⽂件当前的⾏号
__DATE__ //⽂件被编译的⽇期
__TIME__ //⽂件被编译的时间
__STDC__ //如果编译器遵循ANSI C(C语言标准),其值为1,否则未定义//vs并未完全遵守

C语言设置的预定义符号,可以直接使用,预定义符号也是在预处理期间处理的
在这里插入图片描述

并且预处理后代码中**预定义符号**(你猜为什么叫预定义符号)就被替换了
printf("%s\n",C:\code\c-language-411\test_9_5\test_9_5\test.c)以下类推
63
Sep  5 2024
19:58:36
#include <stdio.h>
#define M 100
#define STR "hehe"
#define reg register
int main()
{
	int arr[M] = { 0 };     
	int a = M;
	printf("%d\n", M);  100 大家都是预处理的时候就已经换到printf("%d\n",100)这种了
	printf(STR);    hehe
	reg int b= 10;//预处理后是register int b=10
	return 0;
}

1.2:关于define的一些规则

#define不要加;

#define M 100
if(a)
max=M;//这里的;让if else语句分开了本来是if(a)
else                                   max=M
max=0;                                else max=0;

但是有一种用法

#define CASE breakcase
int main()
{
	int a = 5;
	switch (a)
	{
	case 1:
		CASE 2 :
			CASE 3 :
			CASE 4 :
			CASE 5 :
			CASE 6 :
			break;
	}
	return 0;
}

3.1define 定义宏 (宏里面的参数是整体替换的,并不会算出一个结果)

#define 机制包括了⼀个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏
(define macro)。

#define name(参数)替换的内容 (空格隔开)
#define ADD(n) ((n)*(n)) 这里的括号尽量不要省,不然容易错误
#define SQUARE(n) n+n
int main()
{
	int ret = 10 * SQUARE(5);     **结果是55不是100,变成了10*5+5**
	printf("%d", ret);
	return 0;

3.2 带有副作用的宏参数

当宏参数在宏的定义中出现超过⼀次的时候,如果参数带有副作⽤,那么你在使⽤这个宏的时候就可
能出现危险,导致不可预测的后果。副作⽤就是表达式求值的时候出现的永久性效果。

#define MAX(a,b) (a)>(b)?(a):(b)
int main()
{
	int a = 10;
    int b = 20;
    int ret = MAX(a++, b++);
    printf("ret=%d,b=%d", ret, b);21,22
	return 0;
}

在这里插入图片描述

4# 和##

4.1#(只能出现在宏体)

在这里插入图片描述

4.2##(记号粘合)

在这里插入图片描述

5.1#undef

#undef NAME (取消定义)

5.2 条件编译

调试性的代码,删除可惜,保留⼜碍事,所以我们可以选择性的编译。
在这里插入图片描述

6.头文件包含

(1):本地文件包含(一般这指自己创建的头文件的包含) #include “test.h”
> 查找策略:先在源文件所在目录下查找,如果该头⽂件未找到,编译器就像查找库函数头文件⼀样在标准位置查找头文件。
> (先在自己这个文件目录下找,找不到去库函数里面找)
> 如果找不到就提示编译错误。  
> Linux环境的标准头⽂件的路径:  /usr/include   
>  VS环境的标准头文件的路径: 
> C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include 
> //这是VS2013的默认路径 注意按照⾃⼰的安装路径去找
(2):库文件包含 #include <stdio.h>

查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。

这样是不是可以说,对于库文件也可以使⽤ “” 的形式包含?

答案是肯定的,可以,但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了。

7.如何避免重复包含同一个头文件:

每次编译都要删除#include,然后用包含头文件的内容替换,头文件包含10次,替换10次,test.h文件的内容被包含在test(如果test.h文件比较大,这样预处理后代码量会剧增。如果工程比较大,有公共使用的头文件、被都能使用,又不做任何的处理,**那么后果真的不堪设想**。

如何解决头文件被重复引入的问题?
答案:条件编译。

每个头文件的开头写:

方法一:这种方法通过检查一个特定的宏是否已经被定义来决定是否包含头文件的内容.如果宏已经定义(意味着头文件已经被包含过一次),则跳过头文件的内容。

#ifndef __TEST_H__
#define __TEST_H__
#endif //__TEST_H__
这种方法通过检查一个特定的宏是否已经被定义来决定是否包含头文件的内容.
如果宏已经定义(意味着头文件已经被包含过一次),则跳过头文件的内容。

方法二:
#pragma once提供了另一种更简洁的方法来实现同样的功能。使用#pragma once,编译器在遇到这个指令时会确保当前头文件在同一个编译单元中只被包含一次,无论它是否被多次显式包含。

#pragma once

与宏定义保护相比,#pragma once的优点是:

  • 更简洁,不需要定义和检查宏。
  • 减少了命名冲突的风险,因为不需要为每个头文件创建一个唯一的宏名。
  • 在某些情况下,可以稍微提高编译速度,因为编译器可能能够更有效地优化包含关系

但是:需要注意的是,#pragma
once是非标准的,这意味着它的行为可能不是所有编译器都一致。但幸运的是,几乎所有现代主流编译器都支持这个指令,并且其行为也基本一致。因此,在大多数情况下,#pragma once是一个安全且方便的选择。

上述就是编译(包括预处理详解)和链接的全部内容了
能看到这里相信您一定对小编的文章有了一定的认可,有什么问题欢迎各位大佬指出
欢迎各位大佬评论区留言修正

您的支持就是我最大的动力请添加图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886483.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

戴尔电脑怎么开启vt虚拟化_戴尔电脑新旧机型开启vt虚拟化教程

最近使用戴尔电脑的小伙伴们问我&#xff0c;戴尔电脑怎么开启vt虚拟。大多数可以在Bios中开启vt虚拟化技术&#xff0c;当CPU支持VT-x虚拟化技术&#xff0c;有些电脑会自动开启VT-x虚拟化技术功能。而大部分的电脑则需要在Bios Setup界面中&#xff0c;手动进行设置&#xff…

SpringCloud入门(九)Feign实战应用和性能优化

一、Feign实战应用 Feign的客户端与服务提供者的controller代码非常相似&#xff1a; 有没有一种办法简化这种重复的代码编写呢&#xff1f; 方式一&#xff1a;继承 优点&#xff1a; 简单。实现了代码共享。 缺点&#xff1a;服务提供方、服务消费方紧耦合。参数列表中的注解…

vscode安装及c++配置编译

1、VScode下载 VS Code官网下载地址&#xff1a;Visual Studio Code - Code Editing. Redefined。 2、安装中文插件 搜索chinese&#xff0c;点击install下载安装中文插件。 3、VS Code配置C/C开发环境 3.1、MinGW-w64下载 VS Code是一个高级的编辑器&#xff0c;只能用来写代…

Coggle数据科学 | Kaggle赛题解析:CMI 体育损伤指数预测

本文来源公众号“Coggle数据科学”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;Kaggle赛题解析&#xff1a;CMI 体育损伤指数预测 赛题名称&#xff1a;Child Mind Institute — Problematic Internet Use 赛题类型&#xff1a…

Windows 环境上安装 NASM 和 YASM 教程

NASM 和 YASM NASM NASM&#xff08;Netwide Assembler&#xff09;是一个开源的、可移植的汇编器&#xff0c;它支持多种平台和操作系统。它可以用来编写16位、32位以及64位的代码&#xff0c;并且支持多种输出格式&#xff0c;包括ELF、COFF、OMF、a.out、Mach-O等。NASM使用…

GS-SLAM论文阅读笔记--GEVO

前言 这篇文章看着就让人好奇。众所周知&#xff0c;高斯是一个很不错的建图方法&#xff0c;但是本文的题目居然是只用高斯进行单目VO&#xff0c;咱也不知道这是怎么个流程&#xff0c;看了一下作者来自于MIT&#xff0c;说不定是个不错的工作&#xff0c;那就具体看看吧&am…

LeetCode从入门到超凡(五)深入浅出---位运算

引言 大家好&#xff0c;我是GISer Liu&#x1f601;&#xff0c;一名热爱AI技术的GIS开发者。本系列文章是我跟随DataWhale 2024年9月学习赛的LeetCode学习总结文档&#xff1b;本文主要讲解 位运算算法。&#x1f495;&#x1f495;&#x1f60a; 一、 位运算简介 1.什么是位…

简易CPU设计入门:取指令(三),ip_buf与rd_en的非阻塞赋值

在开篇&#xff0c;还是请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&…

【重学 MySQL】五十一、更新和删除数据

【重学 MySQL】五十一、更新和删除数据 更新数据删除数据注意事项 在MySQL中&#xff0c;更新和删除数据是数据库管理的基本操作。 更新数据 为了更新&#xff08;修改&#xff09;表中的数据&#xff0c;可使用UPDATE语句。UPDATE语句的基本语法如下&#xff1a; UPDATE ta…

【ADC】噪声(1)噪声分类

概述 本文学习于TI 高精度实验室课程&#xff0c;总结 ADC 的噪声分类&#xff0c;并简要介绍量化噪声和热噪声。 文章目录 概述一、ADC 中的噪声类型二、量化噪声三、热噪声四、量化噪声与热噪声对比 一、ADC 中的噪声类型 ADC 固有噪声由两部分组成&#xff1a;第一部分是量…

【重学 MySQL】四十六、创建表的方式

【重学 MySQL】四十六、创建表的方式 使用CREATE TABLE语句创建表使用CREATE TABLE LIKE语句创建表使用CREATE TABLE AS SELECT语句创建表使用CREATE TABLE SELECT语句创建表并从另一个表中选取数据&#xff08;与CREATE TABLE AS SELECT类似&#xff09;使用CREATE TEMPORARY …

【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收

文章目录 1. 标记-清除2. 复制算法4. 标记-整理4. 分代回收 把标记为垃圾的对象的内存空间进行释放。主要有三种释放方式 1. 标记-清除 把标记为垃圾的对象&#xff0c;直接释放掉&#xff08;最朴素的做法&#xff09; 此时就是把标记为垃圾的对象所对应的内存空间直接释放。…

本地化测试对游戏漏洞修复的影响

本地化测试在游戏开发的质量保证过程中起着至关重要的作用&#xff0c;尤其是在修复bug方面。当游戏为全球市场做准备时&#xff0c;它们通常会被翻译和改编成各种语言和文化背景。这种本地化带来了新的挑战&#xff0c;例如潜在的语言错误、文化误解&#xff0c;甚至是不同地区…

k8s中,ingress的实现原理,及其架构。

图片来源&#xff1a;自己画的 图片来源&#xff1a;k8s官网 首先&#xff0c;什么是ingress? 是服务还是控制器&#xff1f; 都不精确 ingress是一个api资源 service和deployment也是api资源。 这几个相互协作&#xff0c;组建成一个对外提供服务的架构。 ingress提供的…

MDM监管锁系统上锁流程

上锁与解锁 上锁设备 完整的上锁流程可参考: https://b23.tv/UvM35sU 上锁需要已经注册了一个普通用户 并使用管理员分配了台数 且有可用的MDM证书和ABM证书(公有和私有的都可以 只要有可用的就可以) 一部用来上锁的手机 链接wifi wifi必须要是2.4g频段 不要使用5gwifi 上锁…

HTTPS协议详解:从原理到流程,全面解析安全传输的奥秘

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

(done) 声音信号处理基础知识(11) (Complex Numbers for Audio Signal Processing)

参考&#xff1a;https://www.youtube.com/watch?vDgF4m0AWCgA&t1047s 似乎是因为信号处理需要使用复数&#xff0c;作者花了一节课介绍复数 据油管主所说&#xff0c;声学信号处理中引入复数的原因是&#xff1a;快速完成部分计算 这里的例子是&#xff0c;当我们做傅里…

行为型模式-命令-迭代-观察者-策略

命令模式 是什么 将一个请求封装成为一个对象, 从而可以使用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及可以撤销的操作 实例 请求封装成为对象 //用来声明执行操作的接口 public abstract class Command { protected Receiver receiver; public Comma…

物联网智能项目全面解析

目录 引言 一、物联网概述 1.1 什么是物联网 1.2 物联网的历史与发展 二、物联网智能项目分类 三、关键组件与技术 3.1 传感器和执行器 3.2 连接技术 3.3 数据处理与分析 3.4 用户界面 四、物联网智能项目案例分析 4.1 智能家居 4.2 智慧城市 4.3 工业物联网 4.4…

react-问卷星项目(3)

项目实战 React Hooks 缓存&#xff0c;性能优化&#xff0c;提升时间效率&#xff0c;但是不要为了技术而优化&#xff0c;应该是为了业务而进行优化 内置Hooks保证基础功能&#xff0c;灵活配合实现业务功能&#xff0c;抽离公共部分&#xff0c;自定义Hooks或者第三方&am…