带volatile限定类型的强制转换写法是否能保证volatile访问?
内存映射IO代码中的volatile访问有效性问题
我见过如下用于写入内存映射IO的代码结构:
*((volatile unsigned int *)0xDEADBEEF) = 0x00;
但这种写法是否能保证是volatile访问?1
结合C标准中强制转换运算符的相关变更,我对这个问题进行了分析:
C11标准(N1570)相关条款
§6.5.4第5款规定:
在表达式前添加带括号的类型名会将表达式的值转换为指定类型,这种结构称为强制转换。104) [...]
对应的脚注104:
- 强制转换不会生成左值。因此,转换到限定类型的效果与转换到对应非限定类型的效果相同。
C17标准(N2310)相关条款
§6.5.4第5款规定:
在表达式前添加带括号的类型名会将表达式的值转换为指定类型的非限定版本,这种结构称为强制转换。108) [...]
对应的脚注108:
- 强制转换不会生成左值。
两个版本的标准均包含以下内容:
N2310 §6.5.3.2第4款:
一元*运算符表示间接寻址。[...];如果它指向一个对象,结果是指定该对象的左值。如果操作数的类型是“指向type的指针”,结果的类型是“type”。[...]
不同标准下的结论
- C17标准:结论明确。上述代码等价于
*((unsigned int *)0xDEADBEEF) = 0x00;,即强制转换过程中volatile限定符会被丢弃,因此该操作不属于volatile访问——即便转换表达式中包含volatile关键字。 - C11标准:存在不确定性:
- 若将脚注视为强制性规则,那么该写法同样不属于volatile访问,因为脚注明确“转换到限定类型的效果与转换到对应非限定类型的效果相同”;
- 但如果仅依据§6.5.4第5款的正文描述,可能会认为这属于volatile访问。不过标准中是否存在其他条款明确说明这种情况不属于volatile访问?
可确保volatile访问的写法
为完整起见,以下写法能保证是volatile访问:
volatile unsigned int *mem = (unsigned int *)0xDEADBEEF; *mem = 0x00;
1假设写入volatile限定类型的对象被定义为对该对象的访问;参考:
N1570 §6.7.3第8款:
[...] 对volatile限定类型对象的访问构成什么由实现定义。
内容的提问来源于stack exchange,提问作者andiluk
相关产品推荐
相关产品推荐

