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

C语言(语句底层实现)

C语言

if 与 switch 原理区别

if-else结构灵活,支持复杂的判断语句
在条件可预测的情况中,将更常触发的if放在考前位置,效率会好一点点

switch的判断条件开销均衡,但判断条件只能是类整型常量。当case数量>3个时会有优化:
其实现结构有4种,其中第二种方案是,当条件大概是线性的时:(比如条件分别是1 9 2 6 4 3 排序后:1 2 3 4 6 9)
收集每个case的代码起始地址,用他们的地址做一个表(数组),switch条件是多少,就读取表对应的内存地址,然后直接跳转到地址所在的代码区执行,直到遇到jmp(break),没有jmp跳转的话就会继续执行到相邻的下一个case(穿透),defalt可以写在多个case中间也没问题,汇编代码会按照C代码的书写顺序编写汇编指令。
红框就是建立的那个数组的基地址:

循环

执行效率最高的是do while 最低的是for
循环解决线性问题更方便,非线性问题往往用递归更容易解决

函数调用实现

数据存储是栈结构,根据栈增长方分为0地址增长(栈顶为0,到0则栈溢出,x86架构就是) 或 高地址增长

调用约定

调用方 与 被调用方需要约定:
1.参数传递方向(参数列表多个参数,是从左到右还是相反)
2.传输媒介(栈 或 寄存器)
3.返回值在哪里
4.调用方 或 被调用方 谁来清理参数占用的内存
举例:
__cdecl: 从右往左传参,传输媒介为栈,返回值在寄存器,调用方释放参数空间 (通用)
__stdcall:从右往左传参,传输媒介为栈,返回值在寄存器,被调用方释放参数空间 (通用)
__fastcall:左数前两个参数寄存器传,其他用栈传(从右往左),返回值在寄存器,被调用方释放参数空间 (微软)

int__cdeclFun(inta,intb)//返回值与函数名之间写调用约定,编辑器根据所选编译选项会自动填写,因此往往可以省略

保存返回地址

保存调用方的栈信息

为将来回到调用方保存必要的信息,也就是前一个函数的栈顶

更新当前栈底到栈顶

函数执行完要回恢复到前一个栈函数的栈顶,也就是当前函数的栈底
保存调用方的栈底:将调用方的 ebp 压栈,然后将当前 ebp 指向当前栈顶。
恢复调用方的栈帧:函数返回前,将 esp 恢复为 ebp 的值,再弹出保存的调用方 ebp,使栈顶回到调用方的栈顶。

为局部变量申请空间

抬高栈顶,多的部分就是放了局部变量

保存寄存器环境

把之前函数使用的寄存器原值保存,方便将来调用结束出栈时恢复上一个函数的寄存值数据(最多只有3个 ebx, esi, edi)

/ZI /Zi 调试选项

如果启用了调试信息开关,将局部变量初始化为0xcccccccc(烫烫烫烫)
未启用则没有这一步

执行函数体

举例:main函数数据的栈结构

栈里存的都是 局部变量 和 参数变量

函数调用结束后,将以上步骤逻辑反这来一次就可以了
1.恢复原寄存器数据
2.释放局部变量空间
3.得到调用方的栈地址
4.按照不同的调用约定,相反操作
__cdecl 返回到刚刚拿到的调用方的栈地址的地方,现在就相当于主人换成了调用方,当前栈顶就是刚刚执行完成的函数返回值的地址调用方清理参数空间
其他约定就 拿到调用方地址后,先清理参数空间,再返回到调用方地址。

执行完毕

如此也能很直观的理解递归为什么占内存了,每调用一次自身,就开了一次栈空间,要是退出逻辑没写好,很容易就栈溢出了。

除了栈,数据在内存种还有以下几个分区

data区

全局变量 静态变量 常量
0x0042开始

已初始化数据区

0x0042开始

只读区

常量

可读可写区

全局变量 静态变量
vc6编译的exe会将已声明的变量内容放在exe中,程序运行时就会把该数据拿到发在程序模块基地址0040000(vc6可设基地址,必须是页边界,且不能是内核的和已占用的那些地址)

未初始化数据区

未初始化的变量在0x0046

代码区

机器代码

ps: if for 后只有一行逻辑时,花括号{}可以省略,但不建议,因为当这一行是宏,而宏的内容有多行时,执行结果就不是预期的样子了。
goto 语句后边跟的标号,有时会看到两个标号相减的逻辑,这其实是在求段代码的长度。

http://www.jsqmd.com/news/694226/

相关文章:

  • Mac 本地跑大模型完全指南:你的苹果电脑就是 AI 工作站
  • Word 自动保存失效、文档异常卡顿怎么办?一文解决 Cobra DocGuard 加载项干扰问题
  • 北京永利鑫达起重:承揽设备移位大件运输合规服务商盘点答疑 - 海棠依旧大
  • 人大金仓KingbaseES kdb_schedule插件:从零构建自动化计划任务
  • 2026年3月正规的出口退税咨询公司推荐,工商注册/外贸公司注册/公司注册,出口退税服务公司找哪家 - 品牌推荐师
  • 收藏!2026 年版大模型零基础入门指南,程序员小白快速学懂 AI 大模型
  • 学术合法性的本质之争:主流体系批判与贾子理论的价值重构
  • 别再死记硬背了!用Python可视化带你秒懂元素周期表电子排布规律
  • AzurLaneAutoScript完整指南:碧蓝航线终极自动化脚本快速上手
  • 别再乱选WiFi信道了!手把手教你用WiFi Analyzer优化2.4G/5G家庭网络(附避坑指南)
  • 【OSG学习笔记】Day 64: Scribe(刻线/轮廓高亮)
  • 何帆律师:只站被保险人一边 绝不帮保险公司打拒赔官司 - 测评者007
  • TVA检测技术在普通电子元器件领域的全维度解析(6)
  • 跨平台资源下载神器:3步搞定全网视频音频图片下载
  • 科技领袖的双面影响:创新与争议的边界
  • 408复试通关指南:从协议栈到内存管理的核心脉络
  • 【ArkUI】使用 Grid/GridItem 组件构建网格显示
  • 2026年IP查询工具怎么选?从临时查询到风控落地的完整选型指南
  • 北京起重吊装搬运公司怎么选?大件运输重物移位服务商优选榜单 - 海棠依旧大
  • Spring StopWatch源码小探:除了计时,它还在注释里‘藏’了哪些设计哲学?
  • 别再只盯着基波了!手把手教你用Simulink搭建PMSM的五七次谐波抑制模型(附源码)
  • 本科论文降AI率工具怎么选?亲测有效指南
  • SpringCloud Alibaba微服务链路追踪实战:Sleuth+Zipkin vs SkyWalking,我该选哪个?
  • 西安财经大学MPAcc复试真汇总(2015-2025)Word高清版|备考专用资料包
  • Elasticsearch核心架构:集群(Cluster)原理详解与核心作用
  • PROGPPCNEXUS读写烧录刷写软件 - 适用于飞思卡尔MPC55xx/56xx/57xx...
  • Unlock Music技术方案:如何彻底解决音乐平台加密格式的跨平台兼容难题
  • BitNet b1.58-2B-4T-gguf效果展示:中文古诗续写、技术术语解释、英文翻译对比
  • 企业内部通讯软件|打造企业专属高效沟通体系
  • handsontable输入中文第一个字母丢失问题