栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Linux调试私房菜(八)混淆指针与数组的问题、volatile,让我保持原样

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux调试私房菜(八)混淆指针与数组的问题、volatile,让我保持原样

十六、混淆指针与数组的问题 1. 下面的程序输出什么?

2. 实例分析:指针 == 数组  ?

main.c

define.c

3. 再论指针和数组
  • 指针
    • 本质为变量,保存的目标值为内存地址
    • 指针运算与*操作符配合使用能够模拟数组行为
  • 数组
    • 数组是一段连续的内存空间
    • 数组名可看做指向数组第一个元素的常量指针
4. 在C语言层面中的等价关系

5. 问题:在二进制层面,指针和数组是否等价? 6. 编程实验:数组与指针深度分析

test.c

7. 结论
  • 指针与数组在二进制层面的操作完全不同
  • 指针操作:先寻址,再对地址单元进行操作
  • 数组操作:直接针对地址单元进行操作
8. C/C++编译器的天生缺陷
  • 由4个子部件组成(预处理器,编译器,汇编器,链接器)
  • 每个子部件独立工作,相互之间没有通信
  • 语法规范只在编译阶段(编译器)有效(如:类型约束,保护成员)
  • 编译器部件对各个源文件进行独立编译(认为源文件相互独立)
9. 问题本质

10. 编程实验:本质分析

11. 解决方案
  • 尽可能不使用跨文件的全局变量(非static全局变量)
  • 当必须使用时,在统一固定的头文件中声明(global.h)
  • 使用跨文件全局变量的源文件直接包含global.h
  • 定义跨文件全局变量的源文件也需要包含global.h
12. 小贴士:声明和定义不同
  • 声明只是告诉编译器,目标存在,可使用
  • 定义实际为目标分配内存(变量)或确定执行流(函数)
  • 理论上,任何目标都需要先声明,再使用
  • C/C++语言允许声明与定义的统一
13. 编程实验:解决方案

global.h

14. 小结
  • C/C++语言中的指针与数组在部分情况可等价
  • 指针与数组在二进制层面的操作完全不同
  • C/C++编译器忽略了源码间的依赖关系
  • 在统一固定的头文件中声明跨文件使用的全局变量(global.h)
  • 使用跨文件全局变量的源文件直接包含global.h

十七、volatile,让我保持原样 1. 嵌入式开发中的常见情形

2. 实例分析:设备启动及初始化

main.c

device.c

未优化

已优化

3. 问题分析
  • 编译优化时,编译器根据当前文件进行优化
  • 编译器能够发现变量 “不可能” 被改变(const全局变量)
  • 为了效率上的提高,编译将变量值进行缓存
  • 缓存的方式为:把变量值从内存中读取进入寄存器
  • 每次访问变量时直接从寄存器读取对应值
4. 解决方案
  • 使用volatile修饰可能被 “意外” 修改的变量(内存)
    • volatile修饰的变量是一种 “易变的” 变量
    • volatile可理解为 “编译器警告指示字”
    • volatile告诉编译器必须每次去内存中取变量值
5. 编程实验:使用volatile修饰变量

main.c

device.c

6. 问题

如何理解const和volatile同时修饰变量?在语义上是否矛盾?

7. const 和volatile
  • const表示被修饰的变量不能出现在赋值符号左边
  • volatile表示使用变量时直接从内存取值
  • const和volatile同时修饰变量时互不影响其含义

8. 小结
  • 编译优化时,编译器只根据当前文件进行优化
  • 编译器的优化策略可能造成一些“意外”
  • volatile强制编译器必须每次从内存中取变量值
  • const和volatile同时修饰变量时互不影响其含义

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/980334.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号