[C语言]-基础知识点梳理-编译、链接、预处理

news2024/9/30 17:38:10

前言

各位师傅大家好,我是qmx_07,今天来给大家讲解以下程序运行会经历哪些事情

翻译环境和运⾏环境

在ANSIC的任何⼀种实现中,存在两个不同的环境

  • 第1种是翻译环境,在这个环境中源代码被转换为可执⾏的机器指令(⼆进制指令)
  • 第2种是执⾏环境,它⽤于实际执⾏代码。

翻译环境

在这里插入图片描述

1.组成一个程序的每个源文件通过编译过程分别转换成目标代码(object code)。
2.每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
3.链接器同时也会引入标准C函数库中任何被该程序所用到的函数,而且它可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。

预编译

预处理阶段主要处理那些源⽂件中 #开始的预编译指令

gcc -E test.c -o test.i //gcc预编译命令

效果:
在这里插入图片描述
在这里插入图片描述

为什么 test.i文件那么多内容? 这是因为 预编译将头文件包含了进来

预编译效果:

  • 1.头文件的包含
  • 2.删除注释
  • 3.#define的替换等

编译

命令:

gcc -S test.i -o test.s //gcc编译命令

效果:
在这里插入图片描述
编译过程:将预处理后的⽂件进⾏⼀系列的 词法分析、语法分析、语义分析及优化,⽣成相应的
汇编代码⽂件

汇编

命令:

gcc -c test.s -o test.o //gcc汇编命令

效果:

在这里插入图片描述
汇编器:是将汇编代码转转变成机器可执⾏的指令,每⼀个汇编语句⼏乎都对应⼀条机器指令,就是根据汇编指令和机器指令的对照表⼀⼀的进⾏翻译,也不做指令优化

链接

  • 链接是⼀个复杂的过程,链接的时候需要把⼀堆⽂件链接在⼀起才⽣成可执⾏程序。
  • 链接过程主要包括:地址和空间分配,符号决议和重定位等这些步骤。
  • 链接解决的是⼀个项⽬中多⽂件、多模块之间互相调⽤的问题
    -在这里插入图片描述
  • test.c文件 并不知道Add的地址,add.c有定义,需要 将多个符号表合并,才能使用

运行环境

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

预处理详解

预定义符号

C语⾔设置了⼀些预定义符号,可以直接使⽤,预定义符号也是在预处理期间处理的

FILE //进⾏编译的源⽂件
LINE //⽂件当前的⾏号
DATE //⽂件被编译的⽇期
TIME //⽂件被编译的时间
STDC //如果编译器遵循ANSI C,其值为1,否则未定义

效果演示

在这里插入图片描述

define

define定义常量

#define MAX 1000
#define reg register //为 register这个关键字,创建⼀个简短的名字 
#define do_forever for(;;) //⽤更形象的符号来替换⼀种实现 
#define CASE break;case //在写case语句的时候⾃动把 break写上。

代码演示:
在这里插入图片描述

  • 注意:宏定义内容不要加;,容易出现问题

define定义宏

#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)
下⾯是宏的申明⽅式:

#define name( parament-list ) stuff
  • 注意:参数列表的左括号必须与name紧邻,如果两者之间有任何空⽩存在,参数列表就会被解释为stuff的⼀部分
案例

在这里插入图片描述

  • 这段代码 演示过程为 5+1*5+1 ,和结果36有误差
    在这里插入图片描述
  • 注意:括号要加全

宏替换规则

1.在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先被替换。
2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。
3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程

  • 注意:参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
  • 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索

带有副作用的宏参数

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

#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
...
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);//输出的结果是什么

z = ( (x++) > (y++) ? (x++) : (y++));
  • x=6 y=10 z=9 ,这种情况我们可以使用x+1,不要使用自增自减符

宏和函数的对比

在这里插入图片描述
命名规定:宏定义全部大写
#undef:用来去除宏定义

#undef NAME

条件编译

编译⼀个程序的时候我们如果要将⼀条语句(⼀组语句)编译或者放弃是很⽅便的

1.
#if 常量表达式
 //...
#endif
//常量表达式由预处理器求值。
如:
#define __DEBUG__ 1
#if __DEBUG__
 //..
#endif
2.多个分支的条件编译
#if 常量表达式
 //...
#elif 常量表达式
 //...
#else
 //...
#endif
3.判断是否被定义
#if defined(symbol)
#ifdef symbol
#if !defined(symbol)
#ifndef symbol
4.嵌套指令
#if defined(OS_UNIX)
 #ifdef OPTION1
 unix_version_option1();
 #endif
 #ifdef OPTION2
 unix_version_option2();
 #endif
#elif defined(OS_MSDOS)
 #ifdef OPTION2
 msdos_version_option2();
 #endif
#endif

文件包含

  • 如果有多个文件引用,那么在预编译阶段,就会多次加载该头文件内容,浪费资源,该怎么办呢?
#ifndef __TEST_H__
#define __TEST_H__
//头⽂件的内容 
#endif //__TEST_H__

或者

#pragma once

避免头文件重复引用

总结

程序的运行过程,预编译的相关内容理解,大家理解相关内容即可

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[FSCTF 2023]ez_php2

[FSCTF 2023]ez_php2 点开之后是一段php代码&#xff1a; <?php highlight_file(__file__); Class Rd{public $ending;public $cl;public $poc;public function __destruct(){echo "All matters have concluded";die($this->ending);}public function __call…

django宿舍管理系统 ---附源码98595

目 录 摘要 1 绪论 1.1 研究背景与意义 1.2 国内外研究现状 1.3论文结构与章节安排 2 宿舍管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据增加流程 2.2.2 数据修改流程 2.2.3 数据删除流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析…

vue vite创建项目步骤

1. 创建vue项目 node版本需18以上 不然报错 npm init vuelatest2. 项目配置 配置项目的icon配置项目的标题配置jsconfig.json 3. 项目目录结构划分 4.css样式的重置 npm install normalize.cssreset.css html {line-height: 1.2; }body, h1, h2, h3, h4, ul, li {padding…

aspose-words将tinymce中的换页符转换为word的换页符

aspose-words版本&#xff1a;21.1 java&#xff1a;1.8 tinymc&#xff1a;5.0.16 public void convertPageBreak() throws Exception{String sourceHtml "hello<!-- pagebreak -->world";sourceHtml sourceHtml.replaceAll("<!-- pagebreak -->…

鸿蒙崛起,前端/Java人才如何搭上这趟技术快车?

在科技飞速发展的今天&#xff0c;鸿蒙系统的崛起犹如一颗璀璨的新星&#xff0c;照亮了技术领域的新航道。对于前端和 Java 人才来说&#xff0c;这不仅仅是一个新的挑战&#xff0c;更是一次搭乘技术快车、实现职业飞跃的绝佳机遇。 一、鸿蒙崛起之势 鸿蒙系统自诞生以来&…

开放式耳机是什么意思?开放式对比入耳式耳机的音质更通透

开放式耳机是一种无需入耳的蓝牙耳机。它主要提供的是一种自然、开放的音频体验&#xff0c;并且无需封耳&#xff0c;能维持佩戴者对外界的感知和环境的联系。这种耳机并不需要深入耳道&#xff0c;但又能清晰听清耳机传来的内容&#xff0c;所以在佩戴方面会更加舒适。 开放…

告别本地硬件烦恼,一分钟教你用云端部署玩Stable Diffusion!

Stable diffusion有两种部署方式&#xff0c;分别是本地部署和云端部署。 本地部署需要把程序安装到自己的电脑上&#xff0c;因此对设备&#xff08;尤其是显卡显存&#xff09;要求比较高&#xff0c;但很多小伙伴反映自己设备不到位&#xff0c;升级设备费用成本过高&#…

【学习笔记】8、脉冲波形的变换与产生

本章简略记录。 8.1 单稳态触发器&#xff08;脉冲触发&#xff09; 单稳态触发器 应用于 &#xff1a;&#xff08;1&#xff09;脉冲整型&#xff08;2&#xff09;脉冲延时 &#xff08;3&#xff09;定时 单稳态触发器的工作特性&#xff1a; 没有触发脉冲作用时&#xf…

【EI会议征稿通知】 第四届航空航天、空气动力学与机电工程国际学术会议(AAME 2025)

第四届航空航天、空气动力学与机电工程国际学术会议&#xff08;AAME 2025&#xff09; 2025 4th International Conference on Aerospace, Aerodynamics and Mechatronics Engineering 会议将围绕“航天航空科学”、“空气动力学”、“机电工程”、“飞行器技术”等主题展开讨…

为什么制造企业智能化升级需要MES管理系统

在制造业的数字化转型浪潮中&#xff0c;MES管理系统的智能化升级扮演着至关重要的角色&#xff0c;它不仅重新定义了生产管理的边界&#xff0c;还为企业带来了前所未有的竞争力与可持续发展动力。本文将从数据赋能、人机深度融合、资源优化及生态协同四个维度&#xff0c;探讨…

ARM工作模式

ARM ARM架构ARM七个工作模式寄存器异常向量表存储格式&#xff08;内存大小端&#xff09;汇编指令 ARM架构 RAM&#xff1a;随机访问存储器 ROM&#xff1a;只读访问存储器 AHB&#xff1a;先进高速总线 APB&#xff1a;先进外设总线 USB&#xff1a;统一串行总线 norflash&am…

公司如何保护源代码不被员工泄漏?

保护源代码不被员工泄漏的方法&#xff1a; 1、验证&#xff1a;第三方身份验证&#xff0c;能减少账号泄密的风险&#xff1b; 2、法律保护&#xff1a;签署法律文件&#xff0c;可以一定程度上的防止员工主动泄密&#xff1b; 3、隔离控制&#xff1a;实施网络隔离&#x…

UV LED供电为什么要选择使用恒流驱动电源

LED为何一定要恒流供电? 在讨论此议题之前&#xff0c;什么是电源的恒流恒压&#xff1f; 什么是电源的恒流恒压   恒流&#xff0c;就是输出电流是恒定的&#xff0c;但电源电流却不是固定的&#xff0c;标称的电压只是安全上限&#xff1b;恒压&#xff0c;就是输出电压是…

TQRFSOC开发板47DR,100G光口自环测试

本实例将演示如何在RFSOC 47DR开发板上&#xff0c;实现100G光口自环测试。此测试使用光口自环模块实现硬件互联&#xff0c;FPGA中进行25Gbps收发校验&#xff0c;通过vivado的硬件管理器烧写比特流&#xff0c;查看传输误差与眼图。 开发板启动模式设置为JTAG模式&#xff0c…

不用再找了,国内无限制使用GPT 4o的方法【2024年9月 亲测好用】

都知道ChatGPT很强大&#xff0c;聊聊天、写论文、搞翻译、写代码、写文案、审合同等等&#xff0c;无所不能~ 那么到底怎么使用呢&#xff1f;其实很简单了&#xff0c;国内AI产品发展也很快&#xff0c;很多都很好用了~ 我一直在用&#xff0c;建议收藏下来~ 有最先进、最…

SolidityFoundry Merkle Airdrop

Merkle airdrop Merkle Tree&#xff0c;也叫默克尔树或哈希树&#xff0c;是区块链的底层加密技术&#xff0c;被比特币和以太坊区块链广泛采用。Merkle Tree允许对大型数据结构的内容进行有效和安全的验证&#xff08;Merkle Proof&#xff09;。对于有N个叶子结点的Merkle T…

框架——MyBatis的参数传递,基本的增删改

MyBatis环境搭建步骤&#xff08;超全解析&#xff01;&#xff01;&#xff01;&#xff09;&#xff1a; http://t.csdnimg.cn/VDMjDhttp://t.csdnimg.cn/VDMjD 1.参数传递 在AdminDao类中写下面两个方法 单个参数直接传递 &#xff1a; //根据id查询管理员对象 Admin fin…

C语言:函数详解(2)

目录 一、数组做函数参数 二、嵌套调用和链式访问 2.1 嵌套调用 2.2 链式访问 三、函数的声明和定义 3.1 单个文件 3.2 多个文件 一、数组做函数参数 在使用函数解决问题的时候&#xff0c;难免会将数组作为参数传递给函数&#xff0c;在函数内部对数组进行操作。 比如…

推荐大模型书籍|《扩散模型从原理到实战》

就在几年前&#xff0c;“通用人工智能”(Artificial General Inte11igence&#xff0c;AGI)似乎还是一个只存在于科幻小说中的概念&#xff0c;在现实中的实现方法仍在探索中。然而到了2022年&#xff0c;基于大语言模型的AIGC(AI Generated Content)领域的快速发展&#xff0…

List<对象>转JSON字符串以及JSON字符串转List<对象>

签名&#xff1a;但行好事&#xff0c;莫问前程。 文章目录 前言一、工作需求二、List<对象>转JSON字符串三、JSON字符串转List<对象>总结 前言 记录一下List<对象>转JSON字符串以及JSON字符串转List<对象> 一、工作需求 产品需求中有一个需求要求页…