STM32学习笔记之地址 (*(volatile unsigned int *)(x))分析
2016-07-19 22:55
696 查看
学习STM32有很多关于地址直接操作函数和指针这里分析一下,在程序中看到这样一句话:
if((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
其中:
*(vu32*)(0X20001000+4))== (*(__IO uint32_t*)(0X20001000+4))==(*(volatile
unsigned int*)(0X20001000+4))
(*(vu32*)(0X20001000+4)) 通过内存寻址访问地址为(0x20001000
+ 4)中的值
(0X20001000+4)只是一个常量;
(volatile unsigned int*)(0X20001000+4) 将0x20001000
+ 4这个常量强制转化成volatile unsigned int类型的指针;
(*(volatile unsigned int*)(0X20001000+4)) 相对于取0x20001000
+ 4地址处的值。
为什么要将0x20001000
+ 4这个常量强制转化成volatile unsigned int类型的指针呢?
假设定义*P 取地址符 &P 得到P地址,这个地址是随机的系统分配空闲地址,我们不能直接给P赋地址值,因为那样是不合法的,我们只能给指针赋值为NULL。
但是现在必须让指针指向一个已知地址(0X20001000+4),必须转换类型,在地址前面加上指针转换的类型我们这里用的volatile
unsigned int*,如果不转换,不成功。
在具体研究一下指向指针的指针看程序和输出:
![](http://img.blog.csdn.net/20160719225327493?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
现在我们来一行一行的看:
第一个printf语句 a,这个大家都知道啦,输出肯定是63啊,因为十进制99,十六进制就是63啊!
第二个printf语句 pa, pa是不是就代表0x0012ff40啊呵呵!一个变量的本质就是避免程序员和地址打交到啦!04的话就是0012ff44啦!对吧!
第三个printf语句 *pa, *pa就是第二句中的0012ff44取内容啊,当然就是63啦!
第四个printf语句 ppa, ppa呢!通过前面的笔记一看就知道它显示出的值是0012ff40啦!
第五个printf语句,*ppa, *ppa呢!唉!现在看来真是太简单了,显示出0012ff44
第六个printf语句,**ppa, **ppa呢就是0012ff44再取内容嘛!63啦!
通过这么一分析,有木有更清晰一点、绝对不会头晕吧!
假如使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义:
#define RAM_ADDR (*(volatile unsigned long *)0x01234567)
然后就可以用C语言对这个内存地址进行读写操作了。
读:tmp = RAM_ADDR;
写:RAM_ADDR = 0x55;
这里使用 volatile关键字的好处就是:
1.volatile是一个类型修饰符(typespecifier);
2.volatile关键字声明的变量,编译器对访问该变量的代码就不再进行优化;
3.volatile 关键字声明的变量,对变量的存取不能缓存到寄存器,每次使用时需要在内存中重新存取。
if((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)
其中:
*(vu32*)(0X20001000+4))== (*(__IO uint32_t*)(0X20001000+4))==(*(volatile
unsigned int*)(0X20001000+4))
(*(vu32*)(0X20001000+4)) 通过内存寻址访问地址为(0x20001000
+ 4)中的值
(0X20001000+4)只是一个常量;
(volatile unsigned int*)(0X20001000+4) 将0x20001000
+ 4这个常量强制转化成volatile unsigned int类型的指针;
(*(volatile unsigned int*)(0X20001000+4)) 相对于取0x20001000
+ 4地址处的值。
为什么要将0x20001000
+ 4这个常量强制转化成volatile unsigned int类型的指针呢?
假设定义*P 取地址符 &P 得到P地址,这个地址是随机的系统分配空闲地址,我们不能直接给P赋地址值,因为那样是不合法的,我们只能给指针赋值为NULL。
但是现在必须让指针指向一个已知地址(0X20001000+4),必须转换类型,在地址前面加上指针转换的类型我们这里用的volatile
unsigned int*,如果不转换,不成功。
在具体研究一下指向指针的指针看程序和输出:
现在我们来一行一行的看:
第一个printf语句 a,这个大家都知道啦,输出肯定是63啊,因为十进制99,十六进制就是63啊!
第二个printf语句 pa, pa是不是就代表0x0012ff40啊呵呵!一个变量的本质就是避免程序员和地址打交到啦!04的话就是0012ff44啦!对吧!
第三个printf语句 *pa, *pa就是第二句中的0012ff44取内容啊,当然就是63啦!
第四个printf语句 ppa, ppa呢!通过前面的笔记一看就知道它显示出的值是0012ff40啦!
第五个printf语句,*ppa, *ppa呢!唉!现在看来真是太简单了,显示出0012ff44
第六个printf语句,**ppa, **ppa呢就是0012ff44再取内容嘛!63啦!
通过这么一分析,有木有更清晰一点、绝对不会头晕吧!
假如使用一个32位处理器,要对一个32位的内存地址进行访问,可以这样定义:
#define RAM_ADDR (*(volatile unsigned long *)0x01234567)
然后就可以用C语言对这个内存地址进行读写操作了。
读:tmp = RAM_ADDR;
写:RAM_ADDR = 0x55;
这里使用 volatile关键字的好处就是:
1.volatile是一个类型修饰符(typespecifier);
2.volatile关键字声明的变量,编译器对访问该变量的代码就不再进行优化;
3.volatile 关键字声明的变量,对变量的存取不能缓存到寄存器,每次使用时需要在内存中重新存取。
相关文章推荐
- 用Git和Github托管项目入门教程
- 处理浏览器兼容为题之opacity
- maven安装过程和用IDEA创建maven的web项目
- drbd+apache+heartbeat
- nginx安装与配置
- Java反射初级阶段
- 常见一些开发注意细节
- 泛型入门
- 标准模板库STL之list
- 处理 InputMethodManager 内存泄露的正确姿势
- APP开发实战107-WebView缓存
- Hadoop伪分布式安装
- 中文乱码问题
- 大型网站架构演变和知识体系(转载)
- 阿里内部面试总结
- HUE的安装
- C语言实现AES加密解密
- 工作日志——记录工作心得(day2):opensns 二次开发之用户扩展资料的导出
- oracle 11.2 RAC 安装新主机 识别老存储
- bash正则表达式