鱼鹰  鱼鹰谈单片机 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的更多相关文章

  1. C语言进阶——const 和 volatile 分析09

    const只读变量: const修饰的变量是只读的,本质还是一个变量 const修饰的局部变量在栈上分配空间 const修饰的全局变量在全局函数区分配资源空间 const只在编译器有用,在运行期无用 ...

  2. 陈正冲老师讲c语言之const关键字

    1.const 关键字也许该被替换为 readolny const是constant的缩写,是恒定不变的意思,也翻译为常量.常数等.很不幸,正是因为这一点,很多人都认为被const修饰的值是常量.这是 ...

  3. C语言关键字const作用及其应用

    只要学过C语言的,都有知道const这个关键字,知道是用来定义常量的,如果一个变量被const修饰,那么它的值就不能再被改变,那么还有什么其他作用呢? 一.const常用作用 1.修饰局部变量 con ...

  4. C语言之const和define

    const修饰的是只读变量,不是常量,其值在编译时不能被使用,因为编译器在编译时不知道其存储的内容.编译器通常不为普通const只读变量分配存储空间,而使将他们保存在符号表中,这使得他成为一个编译期间 ...

  5. c语言,const被绕过

    注意在现在的gcc中, const可能会被用指针绕过. linux: #include "stdlib.h" #include <stdio.h> int t1() { ...

  6. C语言,const

    const意味着“只读” ubunto下的实验 1). 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的.如果你曾花很多时间清理 ...

  7. c语言 - 关键字const的作用

    const修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的. 1.const char * p1;              //表示p1指向了的字符串不可更改 2.char const ...

  8. C语言:const关键字用法

    参考博客:https://www.cnblogs.com/bianchengzhuji/p/10335837.html const是constant的简写,是不变的意思.但并不是说它修饰常量,而是说它 ...

  9. C语言:const详解

    希望定义这样一种变量,它的值不能被改变,在整个作用域中都保持固定.例如,用一个变量来表示班级的最大人数,或者表示缓冲区的大小.为了满足这一要求,可以使用const关键字对变量加以限定:const in ...

随机推荐

  1. idea的eclipse快速定位link with editor

    eclipse的link with editor,个人感觉非常有用的一个功能 idea也有这个功能autoscroll from source

  2. 洛谷 题解 CF903B 【The Modcrab】

    如果它在接下来一回合能一下就将你KO了,那么,你就十分需要回血(一直回到它一下敲不死你),否则你就一直打它就好了. #include<iostream> using namespace s ...

  3. elasticsearch进行远程访问,所面对的问题解决方案

    elasticsearch6.2进行远程访问,修改yml文件后,启动会报错: 上面四个问题解决方案如下: 问题1,问题2,问题3,解决如下: 注意: 针对第二个问题,你可能在limits.d目录中没有 ...

  4. ros 配置udev

    显示已经链接设备 lsusb 显示挂载点 ls /dev/ttyACM* /dev/ttyUSB* 可以看到 ttyUSB0 和 ttyUSB1 对应哪一个设备不确定,因此,我们就需要一种方法来保证每 ...

  5. error LNK2001: unresolved external symbol __imp__closesocket@4

    环境:Visual C++6.0 问题:链接错误 描述: Linking... NetSrv.obj : error LNK2001: unresolvedexternal symbol __imp_ ...

  6. 微信小程序 基本介绍及组件

    创建项目 微信开发工具深入介绍 https://developers.weixin.qq.com/miniprogram/dev/devtools/devtools.html 基本项目目录 1. 配置 ...

  7. python+pycharm+django admin css样式出问题

    最近打算学习一下Python,基础知识有了大概的了解,想上手搞搞东西. 我用的python 3.5+pycharm+django 1.11.2 在使用Django,打开127.0.0.1:8000/a ...

  8. python--基本语法与变量

    python基本语法与变量 python语句的缩进 Python代码块使用缩进对齐表示代码逻辑,Python每段代码块缩进的空白数量可以任意,但要确保同段代码块语句必须包含相同的缩进空白数量.建议在代 ...

  9. golang glog

    原文链接:https://blog.csdn.net/u010857876/article/details/79094942 Flush log 产生后,会暂存在内存的buffer中.只有显示的调用 ...

  10. 尝试 javascript 一对多 双向绑定器

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...