volatile const的间接变化可以被视为未定义行为吗?
Can indirect change of volatile const be treated as undefined behavior?
volatile写入volatile const是否会引入未定义行为?如果我在写的时候丢掉volatile会怎么样?
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?
Compilable代码
当您试图修改"initial" const
对象时,这是未定义的行为(对于两个语句)。来自C11 (N1570) 6.7.3/p6 类型限定符(强调我的):
如果试图修改用通过使用带有非const限定类型的左值类型,行为未定义。
为完整起见,值得补充的是,标准还规定:
如果试图引用用通过使用带有的左值来限定volatile类型非易失性限定类型,行为未定义
因此后一个语句,即:
*(int *)p = 16;
对于第二个短语也是未定义的(它是一个"double 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
需要告诉编译器"值可能在任何时候改变,即使你认为不应该改变它"。这通常在两种情况下发生:
- 硬件寄存器在软件之外被完全更新——比如串口的状态寄存器,定时器寄存器,或者中断控制器的中断状态寄存器,举几个例子——还有成千上万的其他变化,但它都是相同的思想:硬件改变值,与访问这些寄存器的软件没有直接关系。
- 变量由进程内的另一个线程更新(或者在共享内存的情况下,由另一个进程更新)——同样,编译器将无法"看到"这样的更改。通常,一个人可以通过在等待循环中调用一个函数来编写看起来正常的代码,编译器会重新加载非局部变量的值,但过了一段时间后,编译器决定内联该函数调用,然后意识到代码没有更新该值,所以当你检查"更新"的值并找到编译器已经加载的相同的旧值时,不会重新加载value ->错误。
还需要注意的是,volatile
并不能保证任何类型的线程/进程的正确性——它只是保证编译器不会跳过对该变量的读写操作。它仍然是程序员来确保例如多个值依赖于命令的确更新以正确的顺序,和在系统缓存处理单元之间不一致的,通过软件的缓存是连贯的(例如,CPU和GPU不得使用一致的内存更新,所以写的CPU不到GPU,直到缓存刷新在CPU——再多的应用volatile
代码将解决这个问题)
- 具体来说,标准在哪里规定修改 const 对象是未定义的行为?
- 包括"lvtocon.h",未定义对'operator<<(std::ostream&, char const*)的引用
- 正在通过const-ref未定义的行为捕获新构造的对象
- C++ CMake 构建错误:未定义对"boost::throw_exception(std::exception const&)"的引用
- Cpp 未定义引用 'Apache:: thrift:: transport:: TSocket:: TSocket (std:: string const&, int)'
- 对"displayForStudent(int, int const*, double const*, int)"的未定义引用 collect2.exe:错误:ld 返回 1 个退出状态
- 构建错误:未定义对"cv_bridge::CvImage::toImageMsg() const"的引用
- 对'PreconditionViolatedException::PreconditionViolatedException(std::string const&)'的未定义引用
- Cmake 对 'boost::gregorian::greg_month::as_short_string() const' 的未定义引用
- shared_ptr中对const int的未定义引用
- 对'std::string Helper::ToString<int>(int const&)'的未定义引用
- 错误未定义对"BP::D evice::Create(std::string const&)"的引用
- 对 Stack<int>::p ush(int const&) 的未定义引用
- JsonCpp:未定义的对"Json::Value::operator[](int) const"的引用
- 链接器错误(未定义的引用)与“静态 constexpr const char*”和完美转发
- 在 Ubuntu 14.04 上使用 boost 编译:未定义对 'boost::thread::get_id() const' 的引用
- g++ 4.4 中 std::atomic<const memberfunctionpointer*>::store() 的未定义引用
- 对'icu_56::UnicodeString::UnicodeString(signed char, unsigned short const*, int)' 的未定义引用
- 收到错误"二进制'[':"const typ"未定义此运算符"或"下标需要数组或指针类型
- const_cast const STL 容器,它是未定义的行为