Qwe*_*tiy 3 c c++ volatile undefined-behavior
易失性写入易失性const是否会引入未定义的行为?如果我在写作时放弃挥发怎么办?
volatile const int x = 42;
const volatile int *p = &x;
*(volatile int *)p = 8; // Does this line introduce undefined behavior?
*(int *)p = 16; // And what about this one?
Run Code Online (Sandbox Code Playgroud)
当您尝试修改"初始" const对象时,它是未定义的行为(对于两个语句).从C11(N1570)6.7.3/p6 类型限定符(强调我的):
如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为是未定义的.
为了完整性,它可能值得添加,标准也说:
如果尝试通过使用具有非volatile限定类型的左值来引用使用volatile限定类型定义的对象 ,则行为未定义.
因此后面的陈述,即:
*(int *)p = 16;
Run Code Online (Sandbox Code Playgroud)
对于第二个短语也是未定义的(它是"双UB").
我相信C++的规则是相同的,但是没有C++ 14的副本来确认.
写入最初的变量const是未定义的行为,因此所有示例写入*p都是未定义的.
删除volatile本身并不是不确定的.
但是,如果我们有类似的东西const volatile int *p = (const volatile int*)0x12340000; /* Address of hw register */,那么删除volatile可能会导致硬件更新寄存器值,但您的程序不会提取它.(例如,如果我们"忙等待" while(*p & 0x01) ;,编译器应该重新加载p每次指向的值,但是while((*(const int *)p) & 1) ;,编译器完全可以自由地读取值1,并且如果设置了位0,则重新使用初始值来永久循环).
您当然可以在某些代码中[编辑,不,extern volatie int x;使用然后使用const volatile int *p = &x;,并x通过当前翻译单元之外的其他代码(例如另一个线程)进行更新 - 在这种情况下,删除其中一个const或volatile有效,但如上所述,您可能会"错过" "更新值,因为除非您调用函数,否则编译器不希望全局值在模块外部更新.volatile标准中也禁止通过转换值来取走- 然而,添加const或volatile删除某些内容是有效的,如果引用的原始对象没有它,则再次将其删除].
Edti2:volatile需要告诉编译器"值可能随时改变,即使你认为没有什么应该改变它".一般来说,这种情况在两种情况下发生:
另请注意,这volatile并不能保证任何类型的线程/进程正确性 - 它只是保证编译器不会跳过对该变量的读取或写入.程序员仍然需要确保例如依赖于排序的多个值确实以正确的顺序更新,并且在高速缓存在处理单元之间不一致的系统上,通过软件使高速缓存变得一致[用于例如,CPU和GPU可能不会使用连贯的内存更新,因此在CPU上刷新缓存之前,CPU的写入不会到达GPU - 没有适用volatile于代码的数量将解决此问题]