volatile 如何与 const 一起工作?
Posted
技术标签:
【中文标题】volatile 如何与 const 一起工作?【英文标题】:How does volatile work with const? 【发布时间】:2017-08-29 21:10:12 【问题描述】:我有这个代码,和往常一样,变量“local”的值保持不变,因为它是一个 const。
const int local = 10;
int *ptr = (int*)&local;
printf("Initial value of local : %d \n", local);
*ptr = 100;
printf("Modified value of local: %d \n", local);
虽然,当我将local设置为const volatile时,它会将local的值更改为100。这是为什么呢?
const volatile int local = 10;
int *ptr = (int*)&local;
printf("Initial value of local : %d \n", local);
*ptr = 100;
printf("Modified value of local: %d \n", local);
我理解的 volatile 的唯一含义是它阻止编译器对该变量进行优化,以防万一它的值必须由外部元素更改。但我无法弄清楚 volatile 如何以及为什么会覆盖 const 的功能。
编辑-从所有答案看来,我的代码模棱两可,任何输出都是不可预测的,因为我调用了未定义的行为。
【问题讨论】:
未定义的行为是未定义的。任何结果都取决于您未指定的编译器。 哦,我在使用 c++ 已经快十年了。我实际上是一个业余爱好者。我目前正在练习,所以我不知道特定于 C++ 的良好编程实践。感谢您的信息:) 如果你在 SO 中搜索 const volatile,你会发现一些实际使用的好例子,通常是在嵌入式环境中。 您声明某事为const
。然后你用强制转换颠覆类型系统。然后你无论如何都要修改它。然后你期待理智的结果。看到问题了吗?你的程序有未定义的行为——它被破坏了,你不能期望得到合理的结果。遵循 C++ 的规则是你的工作,不是编译器的工作是警告你所有无效的结构。允许假设(当然)你永远不会调用 UB,所以它可以做任何它喜欢的事情。
@Napstablook - 像(int*)&local;
这样的 C 风格转换告诉编译器“我完全知道这意味着什么,请闭嘴并照做”。并且编译器会按照你告诉它的去做(跳下悬崖),即使它非常清楚这是行不通的。
【参考方案1】:
在 C++ 中,通过指针更改声明为 const 的对象的值 - 就像您在此处所做的那样 - 会导致 未定义的行为,这意味着绝对有可能发生任何事情并且没有完全保证您将看到的内容。
在第一种情况下,您看到了存储在 const 变量中的原始值,但很容易返回显示不同的值。我的猜测是编译器识别出该变量是 const,缓存了该值,然后将其硬编码到程序集中(尽管我不能确定)。
在第二种情况下,我的猜测是编译器识别出变量是易失的,因此没有缓存东西,因为它不能假设程序外部的东西会改变值。但是,您仍然不能假设这将适用于多个编译器或操作系统。
【讨论】:
编译器通常不会生成“程序集”。 啊,我明白了。所以,我们可以说这种行为一开始就与 volatile 无关。 @pvg 你说得对,严格来说,但“汇编”比“生成的本机代码”更容易说。 我认为编译器可以缓存const volatile
变量。 const volatile
实际上意味着“程序不能改变值,但值仍然可以以程序无法预测的方式改变。”
@Ramandeep 的行为与volatile
无关。它与调用 UB 的程序有关,因此无效(并且 any 结果是可以接受的)。【参考方案2】:
编译器不会警告您有关 c 样式转换:
int *ptr = (int*)&local;
这个:
*ptr = 100;
是未定义的行为。
所有这些都与volatile
无关。
【讨论】:
我明白了。让我再找一些例子来弄清楚 volatile 究竟是如何工作的。 @Ramandeep 如果没有适当的硬件(例如绑定到某个地址范围的 FPGA),您将无法设置示例,该硬件实际上会独立于编译器生成的代码更改值。 @user0042 多线程比为其定制硬件更容易。一个不需要的例子是忙循环for (volatile int i = 0; i < 1'000'000; ++i);
。
@DanielH 从另一个线程执行此操作仍然会有 UB。
在那种情况下,我真的看不到任何对 volatile 的有效使用。就像在大多数情况下,它的行为是相当 .... volatile 和不可预测的:P以上是关于volatile 如何与 const 一起工作?的主要内容,如果未能解决你的问题,请参考以下文章