C++中的volatile是啥意思?

Posted

tags:

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

书上没有说,网上找到的“可被隐含地改变”是什么意思?

volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。 volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。 volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。 一般说来,volatile用在如下的几个地方: 中断服务程序中修改的供其它程序检测的变量需要加volatile; 多任务环境下各任务间共享的标志应该加volatile; 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义。 另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。 参考技术A 就象大家更熟悉的const一样,volatile是一个类型修饰符(type specifier)。它是被设计用来修饰被不同线程访问和修改的变量。如果没有volatile,基本上会导致这样的结果:要么无法编写多线程程序,要么编译器失去大量优化的机会。 参考技术B   volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
  volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。

C++ 中的***是啥?

【中文标题】C++ 中的***是啥?【英文标题】:What is top-level in C++?C++ 中的***是什么? 【发布时间】:2021-02-23 18:09:26 【问题描述】:

在example 14 under [dcl.init.list] 中,标准在使用列表初始化来描述代码语义时,在缩小转换的范围内使用术语“***”。我不知道这是什么意思。

这段代码执行没有错误:

int f(int a)  return 1;

int main() 
    int a[] = f(2), f(2.0);  
    int b[] = f(2.0), f(2); // No error because: double-to-int conversion is not at the top-level

我还尝试了以下方法。我认为这与初始化顺序无关:

int f(int a)  return 1;

int main() 
    int a[] = f(2), f(2.0);  
    int b[] = f(2.0), f(2); // double-to-int conversion is not at the top-level
    //int c[] = f(2147483645.0f), f(2); // This is erroring out due to narrowing.
    int d[] = f(2), f(2.0);  // Now I'm sure top-level doesn't mean the order of initialization. 

我想知道什么是***?文档here 和here 没有描述它。

我对这个术语感到好奇的原因是因为我试图了解当隐式调用缩小转换时列表初始化器何时工作。

我也不确定术语。例如,是否存在诸如***类、***类型或***列表初始化器之类的东西?

【问题讨论】:

“没有错误,因为:double-to-int 转换不在顶层” 那么这句话是从哪里来的呢?这是一个警告吗?还有什么?到目前为止,从我们掌握的信息来看,唯一使用它的人就是您;) 请在您的问题中添加关键细节! (但是,标准不是“文档”) @AsteroidsWithWings “此处”链接之一指向标准,其中显示“注意 7:如上所述,列表初始化中的***不允许此类转换。”可以在问题中更清楚地指出,是的 @idclev463035818 我已经修复了它 有时单词只是单词,并没有比从上下文中得到的含义更有意义。是的,可以有一个“***类”,就像你将 3 个盒子叠放在一起就有一个***盒子,每个人都会明白指的是哪个盒子 【参考方案1】:

这不是一个严格定义的术语。但是在您链接的[dcl.init.list]/note-7 中,“在顶层”似乎意味着“直接写在花括号列表中,而不是嵌套表达式中”。

所以,在int x[] = 1.0, f(2.0); 中,1.0 位于顶层,因为它直接写在花括号列表中,但2.0 不是因为它嵌套在函数调用表达式中。

【讨论】:

接受这个作为解决方案,因为它清楚地指出int e[] = 2.0; 是列表初始化上下文中的缩小错误。 @Asteroids With Wings ,您的 cmets 帮助制定了想法。但是,我只能接受一个。 @Jerry 您自己引用的标准中的例子已经指出了这一点,但可以肯定;)【参考方案2】:

这不是一个严格定义的 C++ 标准术语。相反,它只是在草率的英语意义上的意思。您可以想象有人使用其他短语,例如“函数的前面”或“相应的头文件”,这些在技术上不是 C++ 术语,但会被广泛理解。

在这种情况下,它们指的是更高级别的嵌套。例如,考虑这个 sn-p:

void foo() 
    int j[2][2] = 3, 4, 5, 6;

显然43, 4 嵌套更深,而3, 4, 5, 6 嵌套更深。事实上,3, 4, 5, 6 根本没有嵌套。您阅读的文本的作者会将其称为“***”。

另一位作者可能会争辩说foo 处于“顶层”,因此它在一定程度上取决于上下文。在你发布的报价中,意思很清楚。

【讨论】:

并且该标准在讨论这种情况下的某些转换时(note 7)确实以非规范方式简要地使用了这个术语,尽管我实际上看不出double-to-int在哪里受到约束o.O “在您发布的报价中,意思很清楚。” 如果“级别”的意思是“嵌套大括号的级别”,您能否举一个缩小范围的示例允许转换,因为它不在顶层? @HolyBlackCat 好时机 - 请参阅注释 7,这不是您要寻找的规则,但确实总结了它 我可以写这样的东西,而且效果很好:int e = f(2.0);。 AFAIK,它不是***的(假设会出错吗?) @Jerry 你可以写int n = 2.0;。函数调用、数组和嵌套是无关紧要的。【参考方案3】:

这只是一个英文短语,要根据上下文来理解。

[dcl.init.list] 的规则告诉我们列表初始化器中的项目如何不能涉及缩小转换。注释 7 继续提醒我们这一点,使用术语“***”来描述它正在谈论的那些事情(列表的直接“成员”)。

您所指的示例 14 还包括一个示例,其中带有列表初始化的语句恰好包含缩小转换,但注释提醒我们这很好,因为转换发生在“较低级别”的嵌套,再次使用术语“***”来描述在初始化列表中立即列出的实体。不需要对实际列表项应用缩小转换。

“***”一词没有正式的定义;在考虑可能的嵌套时,它应该被解释为英语。

【讨论】:

别忘了,笔记不是规范的。他们的目的是澄清。 @PeteBecker 我知道。因此,它所做的只是“提醒我们”已经给出的规则。 ;) 正如我所说,该术语没有正式的定义(即规范文本中没有任何内容)。【参考方案4】:

前段时间我对此感到困惑,但我想我现在已经很好地理解了这个概念。

在我去解释这个概念之前,必须注意的是,不是顶层或低级的对象,而是顶层或低级的“const”取决于它在表达式或上下文中的位置。

*** const 表示(that) "const" 使对象本身成为 const(无论该对象指向什么)。

低级 const 表示(that) "const" 表示被引用(/指向)的对象是 const。

例如

const int i = 10; // const is indicating that i itself is const so it (const) is top level.

const int const *p = &i; // leftmost const is indicating that "pointed to" is const, so that const is low-level, other const in the expr is top-level.

此外,*** const 可以出现在任何 obj 类型(内置类型、类类型、指针类型)中,而低级 const 出现在复合类型的基类型中,例如指针&参考。

在指针中,low-level 和 top-level 都可以出现,但是在 refs 中,consts 总是低级的,因为 refs 隐含地具有 top-level consts(一旦初始化,refs 就不能绑定到其他 objs ,所以从某种意义上说,它们隐含了***常量)。

希望对您有所帮助。

【讨论】:

好的,谢谢。指针间接是对上述答案的进一步补充。上面的讨论解释了嵌套上下文中的顶层。

以上是关于C++中的volatile是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

C语言中的volatile是啥意思?怎么用?谢了

c语言volatile是啥意思

C++ 中的 volatile 与 mutable

C++ 学习笔记:C++ 中 Volatile 变量学习

c++中的const和volatile知识自我总结

为啥 volatile 在多线程 C 或 C++ 编程中没有用?