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(二进制文件)
链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执行程序。
链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
链接解决的是⼀个项⽬中多⽂件、多模块之间互相调用的问题
三.运行环境
- 程序必须载入内存中。在有操作系统的环境中:⼀般这个由操作系统完成。在独立的环境中(单片机,里面无操作系统),程序的载入必须手工安排,也可能是通过可执行代码置入只读内存来完成。
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); hehereg int b= 10;//预处理后是register int b=10return 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,22return 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是一个安全且方便的选择。
上述就是编译(包括预处理详解)和链接的全部内容了
能看到这里相信您一定对小编的文章有了一定的认可,有什么问题欢迎各位大佬指出
欢迎各位大佬评论区留言修正
您的支持就是我最大的动力
相关文章:

C--编译和链接见解
欢迎各位看官!如果您觉得这篇文章对您有帮助的话 欢迎您分享给更多人哦 感谢大家的点赞收藏评论 感谢各位看官的支持!!! 一:翻译环境和运行环境 在ANSIIC的任何一种实现中,存在两个不同的环境1,…...
【QT Quick】基础语法:基础类与控件
QML 的基础类和控件中,我们可以看到主要的几个分类:基础控件类、窗口类以及组件类。以下是对这些控件及其属性、继承关系等的详细讲解: 控件关系总结 QtObject 是所有 QML 对象的基类。它定义了基础属性,主要用于逻辑和数据封装…...

使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南
使用 SSH 连接 Docker 服务器:IntelliJ IDEA 高效配置与操作指南 本文详细介绍了如何在 2375 端口未开放的情况下,通过 SSH 连接 Docker 服务器并在 Idea 中进行开发。通过修改用户权限、生成密钥对以及配置 SSH 访问,用户可以安全地远程操作…...
Gas费用是什么?
Gas费用是什么? 每5个Byte 需要1个GasGasLimit 用来限制合约最多执行多少次运算GasPrice 每次计算需要支付的费用在Web3的语境中,尤其是在以太坊(Ethereum)这样的区块链平台上,Gas费是一个核心概念。以下是关于Gas费的详细解释: 1. 定义 Gas是以太坊网络上的计算单位,…...
大语言模型(LLM)的子模块拆拆分进行联邦学习;大语言模型按照多头(Multi-Head)拆分进行联邦学习
目录 大语言模型(LLM)的子模块拆拆分进行联邦学习 方式概述 简单示例 大语言模型按照多头(Multi-Head)拆分进行联邦学习 场景设定 多头拆分与联邦学习 示例说明 大语言模型(LLM)的子模块拆拆分进行联邦学习 大语言模型(LLM)的子模块拆分进行联邦学习,主要涉及…...

Qt 概述
1. Qlabel HelloWorld 程序 使用纯代码实现 // widget.cpp Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 给当前这个lable对象,指定一个父对象QLabel* label new QLabel(this);// C语言风格的字符串可以直接…...

移动应用的界面配置-手机银行APP
设置登录界面为线性布局,组件垂直居中排列设置主页为滚动模式,包括布局、添加背景图片设置按钮样式,包括形状、边框线的宽度和颜色 设置登录界面 设置界面为线性布局,组件垂直居中排列 --android:gravity"center_vertical…...

微服务nginx解析部署使用全流程
目录 1、nginx介绍 1、简介 2、反向代理 3、负载均衡 2、安装nginx 1、下载nginx 2、解压nginx安装包 3、安装nginx编辑 1、执行configure命令 2、执行make命令 4、启动nginx 1、查找nginx位置并启动 2、常用命令 3、反向代理 1、介绍反向代理配置 1、基础配置…...

华硕天选笔记本外接音箱没有声音
系列文章目录 文章目录 系列文章目录一.前言二.解决方法第一种方法第二种方法 一.前言 华硕天选笔记本外接音箱没有声音,在插上外接音箱时,系统会自动弹出下图窗口 二.解决方法 第一种方法 在我的电脑上选择 Headphone Speaker Out Headset 这三个选项…...
Unity中Socket_TCP异步连接,加入断线检测以及重连功能
1、服务端 using System; using System.Collections.Generic; using System.Text; #region 命名空间 using System.Net; using System.Net.Sockets; using System.Threading; using UnityEngine; #endregionnamespace AsynServerConsole {/// <summary>/// Tcp协议异步通…...
Android build子系统(01)Ninja构建系统解读
说明:本文将解读Ninja构建系统,这是当前Android Framework中广泛使用的构建工具。我们将从Ninja的起源和背景信息开始,逐步解读Ninja的优势和核心原理,并探讨其一般使用场景。然后介绍其在Android Framework中的应用及相关工具&am…...
徐老师的吉祥数
题目背景 文件读写 输入文件avoid.in 输出文件avoid.out 限制 1000ms 512MB 题目描述 众所周知, 3这个数字在有些时候不是很吉利,因为它谐音为 “散” 所以徐老师认为只要是 3的整数次幂的数字就不吉利 现在徐老师想知道,在某个范围[l,r] …...

使用html写一个能发起请求的登录界面
目录 head部分 内联样式部分 body部分 login-form类的div myModal类的div id script部分 总的代码 界面与操作演示 <!DOCTYPE html> <html lang"en"> <!DOCTYPE html> 这是文档类型声明,告诉浏览器这是一个 HTML文档。 <…...

五子棋双人对战项目(2)——登录模块
目录 一、数据库模块 1、创建数据库 2、使用MyBatis连接并操作数据库 编写后端数据库代码 二、约定前后端交互接口 三、后端代码编写 文件路径如下: UserAPI: UserMapper: 四、前端代码 登录页面 login.html: 注册页面…...
几种操作系统和几种cpu
常见的操作系统:windows,linux,macOS,统信,deepin,raspberry,andriod,iOS,鸿蒙,等等。 常见的cpu:intel,amd,龙芯&#x…...

[Cocoa]_[初级]_[使用NSNotificationCenter作为目标观察者实现时需要注意的事项]
场景 在开发Cocoa程序时,由于界面是用Objective-C写的。无法使用C的目标观察者[1]类。如果是使用第二种方案2[2],那么也需要增加一个代理类。那么有没有更省事的办法? 说明 开发界面的时候,经常是需要在子界面里传递数据给主界面࿰…...

彩虹易支付最新版源码及安装教程(修复BUG+新增加订单投诉功能)
该源码当前版本为较新的版本,新增了订单投诉功能和一套精美的二次元模板。 此版本为全开源版本,所有文件均未加密。系统默认安装完成后无法直接打开,需要进一步配置。 本站特别针对BUG文件进行了修复,且在PHP7.4环境下表现良好。…...
ping香港服务器超时的原因通常有哪些?
Ping命令用于测试计算机与目标服务器之间的网络连接。当您在尝试使用ping命令检测服务器时遇到超时的情况,通常可能是由以下原因造成的: 1. 网络连接问题: - 本地网络故障:如网线损坏、路由器故障或配置不当。 - ISP(互联网服务提…...

书生大模型实战(从入门到进阶)L3-彩蛋岛-InternLM 1.8B 模型 Android 端侧部署实践
目录 1 环境准备 1.1 安装rust 1.2 安装Android Studio 1.3 设置环境变量 2 转换模型 2.1 安装mlc-llm 2.2 (可选)转换参数 2.3 (可选)生成配置 2.4 (可选)上传到huggingface 2.5 (可选) 测试转换的模型 3 打包运行 3.1 修改配置文件 3.2 运行打包命令 3.3 创建签…...
setState是同步更新还是异步更新
setState是同步更新还是异步更新 先说结论setState为什么设计为异步react18之前为什么不确定是同步还是异步呢react18之后setState有哪些改动 先说结论 React18之前:使用了ReactDOM.render,setState在React调度流程中是异步更新,在原生事件和…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...