当前位置: 首页 > 知识库问答 >
问题:

可以用C语言初始化另一个易失性变量吗?

卞博简
2023-03-14

C标准允许根据缺陷报告1688(已于2013年9月解决)使用constexpr volatile变量:

这种组合是有意允许的,在某些情况下可以用来强制常量初始化。

看起来,其目的是只允许构造易失性,这在C 20之前是不可用的。

在某些情况下,当前的编译器在处理constexprvolatile方面仍然存在分歧。例如,此程序通过另一个变量初始化一个这样的变量:

int main() {
    constexpr volatile int i = 0;
    constexpr volatile int j = i;
    return j;
}

它在GCC和MSVC中被接受,但Clang抱怨:

error: constexpr variable 'j' must be initialized by a constant expression
    constexpr volatile int j = i;
                           ^   ~
note: read of volatile-qualified type 'const volatile int' is not allowed in a constant expression
    constexpr volatile int j = i;

在线演示:https://gcc.godbolt.org/z/43ee65Peq

哪个编译器就在这里,为什么?

共有2个答案

邵浩大
2023-03-14

您链接的缺陷报告显示它不应该工作,所以Clang是正确的。

(…)“使用constexpr定义的非易失性对象”(…)是允许的,但这样的变量不能出现在常量表达式中。目的是什么?

但更有趣的是:为什么Clang关心而其他编译器不关心?

在我看来,这是因为JF Bastien,一个在Clang/LLVM世界中非常有影响力的人物,他个人不喜欢volatile:)

很长时间以来,他一直建议将它从语言中删除。因此,如果允许在某个地方禁止volatile,他可能会不遗余力地做到这一点。如果没有其他原因,仅仅是为了防止人们编写代码,如果他的建议最终被接受,这些代码将不得不重写。

他还在CppCon上介绍了他的弃用提案,如果你想知道他的理由。

端木骞尧
2023-03-14

铿锵是正确的。从< code>i初始化< code>j要求在< code>i上执行左值到右值的转换,但是根据[expr.const]/5.9,在常量表达式中不允许在< code>volatile glvalue上执行左值到右值的转换。由于< code>i是一个< code>constexpr变量,因此它必须由常量表达式初始化。

我不知道为什么GCC和MSVC选择不执行这条规则,除了所有的C编译器永远人手不足,不能实现他们被期望的一切。

 类似资料:
  • 主要内容:变量初始化的标准格式,编译器推导类型的格式,短变量声明并初始化正如上一节《 Go语言变量声明》中提到的 Go语言在声明变量时,自动对变量对应的内存区域进行初始化操作。每个变量会初始化其类型的默认值,例如: 整型和浮点型变量的默认值为 0 和 0.0。 字符串变量的默认值为空字符串。 布尔型变量默认为 bool。 切片、函数、指针变量的默认为 nil。 当然,依然可以在变量声明时赋予变量一个初始值。 回顾C语言 在C语言中,变量在声明时,并不会对变量对应内存区

  • 为什么我不能这样做? 我得到: 致命错误:常量表达式包含无效操作 这有什么办法吗?

  • 问题内容: TensorFlow中初始化变量的标准方法是 经过一段时间的学习后,我创建了一组新变量,但是一旦初始化它们,它将重置所有现有变量。目前,解决此问题的方法是保存所需的所有变量,然后在tf.initalize_all_variables调用之后重新应用它们。这有效,但是有点笨拙。我在文档中找不到像这样的东西… 有谁知道初始化未初始化变量的好方法吗? 问题答案: 没有优雅的方法可以枚举图中的

  • 问题内容: 我有一个方法创建一个,另一个方法更改字符串 我的编译器说它“可能尚未初始化”。 有人可以解释吗? 问题答案: 变量可能尚未初始化 在内部定义方法时,必须在其中初始化程序的每个变量中必须先使用一个值的地方。 同样重要的是,您的代码将永远无法正常运行,因为Java中的字符串是不可变的,因此您无法编辑字符串,因此应更改方法。 我将您的代码更改为类似的内容,但是我认为您的编辑方法应该做另一件事

  • 所有的中断函数都能正常工作,但是过程函数却让我很生气。 我会感激任何我没注意的把戏。

  • 问题内容: 如何使用类型初始化变量? 因为我有错误 问题答案: 常量声明不能包含函数调用(某些例外,请参见下文),它们必须在编译时进行评估,而函数调用是在运行时进行的。 引用规格:常量: 常数值由符文,整数,浮点数,虚数或字符串文字表示,标识符表示常数,常数表达式,结果为常数的转换或某些内置结果的值函数,例如应用于任何值,或应用于某些表达式,以及应用于常量,以及应用于数字常量的复数。 并引用Spe