为什么“初始化元素不是常量”......不再起作用?

2024-01-31

static const int a = 42;
static const int b = a;

我预计这样的代码会出现编译错误。初始值设定项必须是常量表达式或字符串文字。存储在具有以下类型的对象中的值int with const类型限定符不是常量表达式。

我编译用-Wall -Wextra -pedantic, 即使-ansi. Then:

  • 代码编译良好gcc8.2 https://godbolt.org/z/mNZ59z和海湾合作委员会8.1
  • 代码无法编译gcc 低于 7.4 https://godbolt.org/z/ke1vnF with error: initializer element is not constant
  • 代码编译良好所有 clang 版本 https://godbolt.org/z/fxXvQr

令人惊讶的是,以下内容:

static const char * const a = "a";
static const char * const b = a;
  • 致力于gcc 8.2 https://godbolt.org/z/ZjSN8X
  • 失败gcc 低于 7.4 https://godbolt.org/z/LHhRmO with error: initializer element is not constant
  • 致力于clang 大于 4.0 https://godbolt.org/z/phNCOR
  • 失败clang 低于 3.9.1 https://godbolt.org/z/NiFB1- with error: initializer element is not a compile-time constant

对于下面的片段,我认为我 100% 确定它不应该编译:

static const int a[] = { 1, 2, 3 };
static const int b = a[1];

, but:

  • 它适用于gcc 8.2 https://godbolt.org/z/27rpkd
  • 它失败了gcc 低于 7.4 https://godbolt.org/z/-IO-sh with error: initializer element is not constant
  • 它在任何版本上都会失败clang https://godbolt.org/z/N2bgo2

我尝试浏览网络寻求解释,这主要是从有关非常量初始化器的旧 stackoverflow 问题中复制代码,并找出它们现在是否有效。我找不到任何相关内容海湾合作委员会 8 的变化 https://gcc.gnu.org/gcc-8/changes.html.

我搞不清楚了。这是预期的行为并且这样的代码应该编译吗?为什么/为什么不? gcc7.4和gcc8.1之间有什么变化?这是编译器错误吗?这是编译器扩展吗?


具有静态存储持续时间的对象的初始化程序需要由常量表达式组成。正如@EugenSh。在评论中观察到,“恒定表达”是一个定义好的术语。具体来说,在 C2011 中,它的主题是第 6.6 节 http://port70.net/~nsz/c/c11/n1570.html#6.6。描述很简单

常量表达式可以在翻译过程中求值,而不是 运行时,因此可以在常量可能出现的任何地方使用 是。

但问题在于细节。常量表达式的语义细节包含常量表达式的特定类型和使用的特定规则。

例如,表达式a在任何情况下都不是“整数常量表达式”,无论类型或constness of a,因此不能在标准要求特定类型的常量表达式的情况下使用,例如位域宽度。

尽管该标准没有给出它的名称,但它为初始化程序中的常量表达式提供了稍微宽松的规则,这就是我们在这里考虑的情况:

这样的常量表达式应为或计算为以下之一 下列的:

  • 算术常量表达式,
  • 空指针常量,
  • 地址常量,或
  • 完整对象类型的地址常量加上或减去整型常量表达式。

术语“算术常量表达式”和“地址常量”也被定义:

算术常量表达式应具有算术类型并且应 仅具有整型常量、浮点常量的操作数, 枚举常量、字符常量、sizeof 表达式 结果是整数常量,并且_Alignof表达式。 [...]

地址常量是一个空指针,一个指向左值的指针 指定静态存储持续时间的对象,或指向 功能指示符;它应使用一元 & 显式创建 运算符或整数常量转换为指针类型,或隐式通过 使用数组或函数类型的表达式。 [...]

没有适合您的各种初始化程序b变量符合这些规则。指定对象的左值表达式const-限定类型不属于允许出现在标准初始化器所要求的任何常量表达式变体中的元素。

该标准通常允许

实现可以接受其他形式的常量表达式。

,但这不会覆盖其对初始值设定项中出现的常量表达式的特定要求。

每个给定的变量声明b违反了出现在约束之外的标准的“应”要求。因此,结果行为是未定义的,但该标准不需要诊断。实现可以接受此类形式作为扩展,正如 GCC 8.2 显然所做的那样,并且 GCC 的-pedantic选项确保仅在标准要求的情况下进行诊断,但标准不包括这些情况。

由于行为未定义,因此观察到的各种实现的行为都不是不合格的。您不能依赖一致的实现来拒绝不合格的代码。在某些情况下(但不是这些)它必须diagnose不符合规定,但即使在这种情况下,无论如何也允许成功翻译。

我搞不清楚了。这是预期的行为并且这样的代码应该编译吗?

不,但是期望它无法编译也是不安全的。

为什么/为什么不?

我在上面解释了为什么各种代码不符合要求,因此可能会被符合要求的编译器拒绝。但另一方面,符合标准的编译器不需要拒绝不符合标准的代码。

gcc7.4和gcc8.1之间有什么变化?这是编译器错误吗?这是编译器扩展吗?

海湾合作委员会显然实施了延期。我不确定这是否是故意的,但这肯定是结果。只要行为是人们天真的所期望的,它看起来就相当自然和良性,除非从 GCC(不)帮助您编写一致代码的角度来看。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么“初始化元素不是常量”......不再起作用? 的相关文章

  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • 以编程方式读取 SQL Server 查询计划建议的 SQL 特定执行的索引?

    如果我在 SSMS 中运行此命令 set showplan xml on GO exec some procedure arg1 arg2 arg3 GO set showplan xml off GO 我获得查询执行中涉及的完整调用堆栈的
  • 为什么pow函数比简单运算慢?

    从我的一个朋友那里 我听说 pow 函数比简单地将底数乘以它的指数的等价函数要慢 例如 据他介绍 include
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 如何使用 Castle Windsor 将对象注入到 WCF IErrorHandler 实现中?

    我正在使用 WCF 开发一组服务 该应用程序正在使用 Castle Windsor 进行依赖注入 我添加了一个IErrorHandler通过属性添加到服务的实现 到目前为止一切正常 这IErrorHandler对象 一个名为FaultHan
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 在mysql连接字符串中添加应用程序名称/程序名称[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在寻找一种解决方案 在连接字符串中添加应用程序名称或程序名称 以便它在 MySQL Workbench 中的 客户端连接 下可见 SQL
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 等待 IAsyncResult 函数直至完成

    我需要创建等待 IAsyncResult 方法完成的机制 我怎样才能做到这一点 IAsyncResult result contactGroupServices BeginDeleteContact contactToRemove Uri
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • String.Empty 与 "" [重复]

    这个问题在这里已经有答案了 可能的重复 String Empty 和 有什么区别 https stackoverflow com questions 151472 what is the difference between string
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • 使用 omp_set_num_threads() 将线程数设置为 2,但 omp_get_num_threads() 返回 1

    我有以下使用 OpenMP 的 C C 代码 int nProcessors omp get max threads if argv 4 NULL printf argv 4 s n argv 4 nProcessors atoi argv
  • 是否可以在不连接数据库的情况下检索 MetadataWorkspace?

    我正在编写一个需要遍历实体框架的测试库MetadataWorkspace对于给定的DbContext类型 但是 由于这是一个测试库 我宁愿不连接到数据库 它引入了测试环境中可能无法使用的依赖项 当我尝试获取参考时MetadataWorksp
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string

随机推荐

  • MySQL 中的事务暂停是如何工作的?

    在 Spring 框架手册中 他们声明对于 PROPAGATION REQUIRES NEW 当前事务将被挂起 暂停交易 是什么意思 超时计时器停止对当前事务计数 这种暂停的实际影响是什么 谢谢你 Asaf 这并不意味着什么特别的 暂停的交
  • Mathematica 协助:使用 /。将方法替换为 IF[] 条件

    首先我要声明 我是一名 Mathematica 新手 这个问题可能很容易回答 但到目前为止 我在互联网上找不到任何针对这个特定问题的帮助 在这里 我基本上总结了我需要我的代码做什么 使用时出现一些问题 将命令替换为IF条件语句 基本上 我有
  • Sql Server 2008 - 换行符和全文查询

    我有一个数据库和一个全文索引表 我们称这张表为test 该表有一个名为testfield 现在 我们只插入一条记录 如下所示 insert into test values word Char 13 test 该查询插入一个带有LINE B
  • 如何选择 numpy 二维数组中唯一元素的所有位置及其周围的边界框?

    我有一个 2D numpy 数组 我想找到所有唯一元素的 每个 位置 我们可以使用以下方法找到独特的元素numpy unique numpyarray 这是棘手的部分 现在我必须知道每个独特元素的所有位置 让我们考虑以下示例 array 1
  • MySQL自动增量加上一列中的字母数字

    我是来自 Oracle 的 MySQL 新手 我需要创建一个表 其中主键位于一列中 但格式如下 X A注明原产国的信件 例如S对于西班牙来说 Z津巴布韦等 我们只有五个原籍国 YYYYMMDD 该格式的日期 9999 4 位办公代码 999
  • 奇怪的超时::控制器操作中的 render_to_string 和 HTTParty 出现错误

    在我的控制器操作中 我使用带有 jbuilder 模板的 render to string 来将 http post 操作的对象渲染到 API 此 API 调用的结果是控制器应该渲染的结果 但是在通过 render to string 渲染
  • Apache Commons Math 的标准差

    我正在使用 Apache Commons Math 计算向量的 SD 问题 我得到的值与手工得到的值不同 DescriptiveStatistics stats new DescriptiveStatistics stats addValu
  • iOS 10 iMessage 贴纸应用中 MSSticker Peels 的回调

    我正在 iOS 10 中尝试贴纸 iMessage 应用程序 但遇到了问题override func didStartSending message MSMessage conversation MSConversation 中的方法MSM
  • 数据绑定布局约束

    我在添加要查看的结束约束时遇到问题
  • Blazor 导航:更新 URL 而不更改重新加载页面

    我在应用程序中使用 URL 参数来表示页面状态 如何在不实际导航的情况下更改 URL Thanks 使用 Blazor 服务器端 您可以使用 JS Interop 来完成此操作并调用history pushState null url 这是
  • 禁用日期选择器弹出窗口中的过去日期

    我有下面的代码片段 其中有日期选择器控件
  • LinearLayoutManager.findFirstVisibleItemPosition() 返回 POSITION_NONE

    我正在尝试做这样的事情 RecyclerAdapter recyclerAdapter LinearLayoutManager recyclerManager set items recyclerAdapter notifyDataSetC
  • 在方向更改时保持列表片段选定项目的位置

    我在另一个片段的左侧有一个列表片段 本质上是标准的单击一个项目并更新右侧的片段模式 当他们单击列表片段中的一项时 他们正在选择新闻文章类别 我需要保留他们旋转设备时选择的任何一项 我怎么做 我当前的代码不起作用 我的代码如下 public
  • Django 1.7+ 相当于 South 的 add_ignored_fields() 是什么?

    回到 Django 的早期版本 我们都使用 South 进行迁移 并且由于它没有我们希望的那么智能 我们有时需要告诉它显式忽略某些字段 因为这些字段太复杂而无法处理 我们这样做是用add ignored fields一切都很顺利 在我们的例
  • 正确地从 DOM 中删除角度组件

    我创建了一个芯片组件 它有一个删除按钮 单击此按钮后 我想从 DOM 中删除整个组件 包括它的包装 HTML 标记 芯片组件 ts Component selector app chips template div class close
  • 在我的 Mac 上制作一个 C 启动器

    我想为我制作的 C 程序制作一个启动器 并且希望它在终端中运行 我该怎么做 我连一丁点的想法都没有 只需创建一个文本文件 将其保存到桌面 例如my C program command 注意 command后缀 然后在文本文件中您可以输入您喜
  • 从右到左的 UI 指南?

    我正在研究对专有 UI 框架 用于桌面应用程序 的 RTL 支持 我想知道 是否有关于如何更改小部件渲染的指南 我正在寻找诸如以下内容的列表 复选框标签位于复选框的左侧 并且右对齐 工具栏按钮从右向左流动 垂直滑块位于左侧 窗户装饰 一般布
  • 用于在 Google 电子表格中保存 URL 的书签

    我想创建一个简单的书签 它获取当前网页 location ref 的 URL 并将其保存在 Google 电子表格中 保存后 我想留在当前网页 我知道写入 Google 电子表格的唯一方法是使用 Google App Script 所以我写
  • JUnit 5 测试套件的 Surefire XML 测试报告

    我刚刚迁移到 JUnit 5 在我的测试套件的 XML 测试报告中看不到任何测试用例 我已经使用 junit platform suite 的新 JUnit 5 语法编写了测试套件 并且套件中的测试均成功运行 这将通过 Surefire 生
  • 为什么“初始化元素不是常量”......不再起作用?

    static const int a 42 static const int b a 我预计这样的代码会出现编译错误 初始值设定项必须是常量表达式或字符串文字 存储在具有以下类型的对象中的值int with const类型限定符不是常量表达