volatile const int ci = 100;这是啥意思?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了volatile const int ci = 100;这是啥意思?相关的知识,希望对你有一定的参考价值。

volatile的本意是“易变的”
提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。
const int ci = 100; 这里定义一个整型常量ci,其值为100.
const表示常量,意思是不会变,不允许变,编译器在编译时会检查是否有对此变量修改的操作,一经发现,报告错误:error: assignment of read-only variable `ci'
这里的const 与 volatile 就相矛盾了
经在linux下测试,volatile 这时不起作用!
参考技术A volatile是易变的意思,每次对这个值的读取都会直接来自寄存器,而不会在缓冲中读取从而影响当前值的正确性,比如说IO口,可以改变,但是改变来自硬件

const是不被程序改变的意思,也就是说程序中的语句是不能改变这个值的,硬件是可以修改的(仍旧以IO举例,每次读取的值都来自硬件,会改变)只要编译器在你的程序中没有发现这个值被显式的被程序(而不是硬件)改变,比如重新对CI赋值等等,那编译就可以通过了

你可以在BAIDU上搜下 volatile 和const的定义,有几篇说的挺好的 可以加深理解

volatile 如何与 const 一起工作?

【中文标题】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 int ci = 100;这是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

volatile 如何与 const 一起工作?

C++ 语法--唯一的难点const和复合类型

6错误代码C3848.

const和volatile

const变量的修改实践

volatile与const综合分析