发布网友 发布时间:2022-04-23 10:30
共3个回答
热心网友 时间:2023-10-11 12:26
首先你必须明白,指针其实是个内存地址,内存地址用一个比较直观的表示方式是一个类似于0x1234这样的数字!
上述例子是个比较常见的宏定义,宏定义的本质只是简单的文本代换,套用你给出的例子,在这句代码以后所有出现了“TWBR ”的地方都用(*(volatile unsigned char *)0x20)代替,所谓宏就是这样。
我再解释一下后面一串东西:0x20是个整数,这里用(volatile unsigned char *)表示对它进行强制类型转化,这样转化后表示0x20是个内存地址,或者是某个寄存器的地址,CPU可以寻址得到,(/*即是个指针,这个指针指向一个char型的变量,前面所述是错误的,它不是一个指针了,而是一个(volatile unsigned char *)类型的指针所指向的地址了*/)最前面的*表示对这个地址取值,也就是对0x20处的内存地址取一个char(一个字节)的内容出来。
另外如果你不知道volatile 关键字的作用的话,着实应该认真看看,在这里挺关键的。volatile 在这里主要作用是防止编译器“自作主张”对其优化从而导致不是每次都从0x20这个地址处取值(它很可能在第二次运行到这句代码的时候用上次运行的结果了)。
另外,可以直接给一个指针变量直接赋值,但是你要注意他的合法性(包括数据类型以及这个数据是否可读可写等,在有OS的环境下更为严格)。
我自己对某些概念理解不够准确,给你造成迷惑,实在抱歉!
热心网友 时间:2023-10-11 12:26
就象大家更熟悉的const一样,volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。
关键在于两个地方:
1. 编译器的优化 (请高手帮我看看下面的理解)
在本次线程内, 当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个寄存器中;以后,再取变量值时,就直接从寄存器中取值;
当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以便保持一致
当变量在因别的线程等而改变了值,该寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致
当该寄存器在因别的线程等而改变了值,原变量的值不会改变,从而造成应用程序读取的值和实际的变量值不一致
举一个不太准确的例子:
发薪资时,会计每次都把员工叫来登记他们的银行卡号;一次会计为了省事,没有即时登记,用了以前登记的银行卡号;刚好一个员工的银行卡丢了,已挂失该银行卡号;从而造成该员工领不到工资
员工 -- 原始变量地址
银行卡号 -- 原始变量在寄存器的备份
2. 在什么情况下会出现(如1楼所说)
1). 并行设备的硬件寄存器(如:状态寄存器)
2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)
3). 多线程应用中被几个任务共享的变量
热心网友 时间:2023-10-11 12:27
是icc里面寄存器的定义吧
0x20是该寄存器的地址,要对这个地址进行读写,首先要把这个数转换为指针,然后通过这个指针读写。volatile是一个修饰符