C语言之const
鱼鹰 鱼鹰谈单片机 2月19日
预计阅读时间: 5 分钟
我们知道,数据分为两种,一种为只读,一种为可读可写,为了防止一些不变的数据被程序意外的修改,有必要对它进行保护。这就是 const 的作用。在单片机中,不变的数据(比如代码,比如用户一些固定不变的数据)一般存放在 FLASH 中,而 FLASH 在一般情况下是只读的(事实上可以通过操作修改 FLASH,这种方式称之为 IAP ,即你可以不断更新程序的原因),而一些可变的数据一般是放在 RAM 中的,这些数据可能被指针意外的修改。所以就需要通过一种方式来将这些数据存放在 FLASH 中以防意外修改,而最好的保护就是硬件水平上的支持,这就是 const 的作用,它可以将你的数据放在 FLASH 中,但它的作用不只是如此。
const: 限定一个变量不允许改变,产生静态作用,const 在一定程度上可以提高程序的安全性和可靠性。
const 推出的初始目的,正是为了取代预编译指令,消除它的缺点,同时继承它的优点。
声明为 const 的变量是不能被用户改变的(意思就是说不允许你通过代码去修改这个值),因为编译器会将该变量放在只读区,比如在 KEIL 开发平台下,声明为 const 的变量放在 FLASH 区,这样即使你使用取地址符 & 获取声明为 const 变量地址,并通过指针进行修改,虽然编译器不报错,但也是无法进行修改的,因为 STM32 进行 FLASH 编程是有条件的。
你会发现虽然 p 获取了 N 的地址,但因为 N 存放在 FLAH(0x0800 0000 开始地址是 FLASH)中,所以即使通过指针的方式也是无法间接改变 N 的值的。
可以看到运行 *p = 4 的代码后,N 并没有发生改变。但是编译器确实也没报错。但是如果你直接使用 N = 4; 的话,肯定是报错的,因为你的 N 已经被申明为 const 了。
《C语言深度剖析》中关于 const 的介绍发现和 KEIL 情况不一样。
在KEIL中进行相关代码的编写,编译,最后可以看到如下结果:
这是仿真模式下两个地址的内容,一个存放在 FLASH,一个存放在 RAM 中,并且当修改 FLAH 的内容之后(因为是软件仿真模式,可以直接修改值),复位重新运行,你会发现 RAM 的内容对应改变了(重新运行后,进入 main 函数之前,有一段拷贝代码,就是函数外申明的一些变量的初始化过程),这就说明,在 STM32、KEIL 环境下,并不是《C语言深度剖析》中说的只有一份内存,而是每一个都有一个,申明为 const 情况跟使用宏定义的方式是一样的。
以下是 Watch 中的内容:

但其实上面的结论是在使用 & 将 N 的地址获取后的结果(从上图可以看到 p 的值),实际上代码中如果没有获取 N 的地址时,情况又不一样了。
内存情况:
在删去获取 N 地址后的内存情况,可以发现 N 的值为 0x2000470,和 FLAH 地址0x08000000 一样。
这像一个地址。但通过 Memory 查看这个地址发现存放的不是 5。
根据 ARM 内核的知识可以知道,0x08000000 地址存放的其实是栈顶指针,也就是说N 存放的是栈顶指针吗?显然不是。
然后对 .map 地址映射文件进行搜索,你会发现,根本没有 N 的地址。这样说来, N在内存的位置对用户是不可见的,而是由编译器自动处理了。
那么有没有办法找到这个拷贝源头呢。之前我说过,先前能找到拷贝的源头纯属偶然,有没有什么方法可以找到呢?这其中的难点就是进入 main 函数之前的那段拷贝代码不是我们用户自己写的,而是 C 编译器自动处理的,怎么办?
这个时候就需要请出一个关键人物:数据观察点(关于数据观察点,将有专门的一小节详细说明,感兴趣的可以关注我)。
我们知道,不管如何,因为 FLASH 存放着变量初始值,然后在程序运行的时候才将FLASH 中的值初始化到 RAM 中去,也就是我们使用的 RAM 变量,那么必然存在通过总线进行数据传输的过程,所以可以通过数据观察点的功能实现对地址的监控,虽然我们不知道 FLASH 的地址,但是我们知道 RAM 的地址,所以只要对变量 i 进行监控,就可以通过内核的寄存器找到 FLASH 地址了。如下:
这里的 0x20000000 就是 i 的 RAM 地址,最终可以找到 FLASH 的位置:
由此可以知道,FLAH 中也是有多个相同副本存在的。
因此可以得出结论,在 STM32、KEIL 的环境下,《C语言深度剖析》对于两者的说法在这里不适用。
看了那么多,没有足够的基础是很难知道我在讲什么,下面用一张图进行说明,希望可以解答你的疑惑。
希望你在看完这张图之后,再回过头看看前面的那些话,对你应该会有帮助的。
-THE END-
C语言之const的更多相关文章
- C语言进阶——const 和 volatile 分析09
const只读变量: const修饰的变量是只读的,本质还是一个变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局函数区分配资源空间 const只在编译器有用,在运行期无用 ...
- 陈正冲老师讲c语言之const关键字
1.const 关键字也许该被替换为 readolny const是constant的缩写,是恒定不变的意思,也翻译为常量.常数等.很不幸,正是因为这一点,很多人都认为被const修饰的值是常量.这是 ...
- C语言关键字const作用及其应用
只要学过C语言的,都有知道const这个关键字,知道是用来定义常量的,如果一个变量被const修饰,那么它的值就不能再被改变,那么还有什么其他作用呢? 一.const常用作用 1.修饰局部变量 con ...
- C语言之const和define
const修饰的是只读变量,不是常量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容.编译器通常不为普通const只读变量分配存储空间,而使将他们保存在符号表中,这使得他成为一个编译期间 ...
- c语言,const被绕过
注意在现在的gcc中, const可能会被用指针绕过. linux: #include "stdlib.h" #include <stdio.h> int t1() { ...
- C语言,const
const意味着“只读” ubunto下的实验 1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的.如果你曾花很多时间清理 ...
- c语言 - 关键字const的作用
const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的. 1.const char * p1; //表示p1指向了的字符串不可更改 2.char const ...
- C语言:const关键字用法
参考博客:https://www.cnblogs.com/bianchengzhuji/p/10335837.html const是constant的简写,是不变的意思.但并不是说它修饰常量,而是说它 ...
- C语言:const详解
希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定.例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小.为了满足这一要求,可以使用const关键字对变量加以限定:const in ...
随机推荐
- vue 结构赋值
- IDEA插件之JProfiler
1.是什么?来用干嘛的? 一个商业授权的Java剖析工具. 用来剖析程序内存.CPU使用情况,找到性能瓶颈,快速定位问题所在. 2.IDEA安装JProfiler插件 (1)File -> Se ...
- 织梦DedeCMS给栏目添加缩略图调用的方法
织梦DedeCMS的栏目调用仅仅只有文字调用,没有栏目缩略图调用,而我们有时候又需要给栏目添加缩略图,并能够在前台调用,就可以试试通过下面的方法,给栏目添加缩略图. 首先要给栏目数据库表添加一个存储缩 ...
- Idea中maven的设置
File->setting 输入MAVEN 看到右侧设置情况 Maven home directory 熟路本地moven 仓库目录:D:/springboot/apach ...
- python+selenium+chrome实现自动登录百度
#python3.4+selenium3.5+chrome版本 63.0.3239.132+chrome驱动chromedriver.exe #实现自动登录百度 from selenium impor ...
- python — 装饰器、迭代器
目录 1 装饰器 2 迭代器 3 可迭代对象 1 装饰器 1.1目的.应用场景: 目的: 在不改变原函数内部代码的基础上,在函数执行前后自定义功能. 应用场景: 想要为函数扩展功能时,可以选择用装饰器 ...
- DFA与动态规划
1.牛客练习赛45 A 给定字符串, 求字符不相邻的"QAQ"子序列个数. $dp[i][0]$ 只匹配一个'Q'的方案数的前缀和. $dp[i][1]$ 只匹配"QA& ...
- Wannafly挑战赛22
B. 字符路径 给一个含n个点m条边的有向无环图(允许重边,点用1到n的整数表示),每条边上有一个字符,问图上有几条路径满足路径上经过的边上的字符组成的的字符串去掉空格后以大写字母开头,句号 '.' ...
- std::string与char*之临时缓冲区
std::string与char*之临时缓冲区 原文:https://blog.csdn.net/hsshh1988/article/details/80689330 c++文件读取流程如下: ifs ...
- JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
js 笛卡尔积算法的实现代码,据对象或者数组生成笛卡尔积,并介绍了一个javascript多重数组笛卡尔积的例子,以及java实现笛卡尔积的算法与实例代码. 一.javascript笛卡尔积算法代码 ...