union '双关语'结构带有“公共初始序列”:为什么 C (99+) 而不是 C++ 规定了“联合类型的可见声明”?

2024-02-11

背景

通过以下方式讨论类型双关的大多数非或实现定义的性质union通常引用以下位,此处通过@ecatmur(https://stackoverflow.com/a/31557852/2757035 https://stackoverflow.com/a/31557852/2757035),关于标准布局的豁免struct具有成员类型的“共同初始序列”:

C11 (6.5.2.3 结构和联合成员; 语义学):

[...] 如果联合包含多个共享公共初始序列的结构(见下文),并且如果联合对象当前 包含这些结构之一,则允许检查 其中任何一个的共同初始部分任何声明 联合的完整类型可见。两个结构共享一个共同初始序列如果对应的成员具有兼容的类型(对于位字段,具有相同的宽度),对于一个或 更多初始成员。

C++03 ([class.mem]/16):

如果 POD-union 包含两个或多个共享公共初始序列的 POD-struct,并且 POD-union 对象当前包含一个 在这些 POD 结构中,允许检查共同的初始值 其中任何一个的一部分。两个 POD 结构共享一个共同的初始序列 如果相应的成员具有布局兼容的类型(并且,对于 位域,相同的宽度)用于一个或多个初始的序列 成员。

这两个标准的其他版本也有类似的语言;从 C++11 开始 使用的术语是标准布局而不是POD.

由于不需要重新解释,这并不是真正的类型双关,只是名称替换应用于union会员访问。 C++17 的提案(臭名昭著的 P0137R1)使用诸如“访问就像提名其他结构成员一样”这样的语言来明确这一点。

但请注意粗体——”联合完整类型声明可见的任何地方" - 该条款存在于 C11 中,但在 2003、2011 或 2014 年的 C++ 草案中却没有(几乎完全相同,但后来的版本用新术语替换了“POD”)标准布局)。无论如何,“可见的声明”union任何 C++ 标准的相应部分中都完全不存在类型位。

@loop 和 @Mints97,在这里 -https://stackoverflow.com/a/28528989/2757035 https://stackoverflow.com/a/28528989/2757035-表明这条线也是C89 中不存在,C99 中首次出现从那时起就一直使用 C(不过,再一次,从未过滤到 C++)。

围绕此的标准讨论

[剪断-看我的回答]

问题

由此,我的问题是:

  • 这是什么意思?什么被归类为“可见声明”?该条款是否旨在缩小或扩大此类“双关语”定义行为的上下文范围?

  • 我们是否可以假设 C++ 中的这种遗漏是故意的?

  • C++ 与 C 不同的原因是什么?C++ 是否只是从 C89 中“继承”了这一点,然后决定 - 或者更糟,forget- 与C99一起更新?

  • 如果差异是故意的,那么C 与 C++ 中的两种不同处理方式有何优点或缺点?

  • 它在编译或运行时有什么有趣的后果(如果有的话)?例如,@ecatmur,在回复我在他的原始答案中指出这一点的评论中(链接如上),推测如下。

我想它允许更积极的优化; C 可以假设 函数参数S* s and T* t即使他们共享一个,也不要使用别名 共同的初始序列,只要没有union { S; T; }正在视图中, 而 C++ 只能在链接时做出这种假设。可能值得 关于这种差异提出一个单独的问题。

嗯,我来了,问一下!我对对此的任何想法都非常感兴趣,尤其是:(任一)标准的其他相关部分、委员会成员或其他受人尊敬的评论员的引用、开发人员的见解,他们可能已经注意到由此产生的实际差异 - 假设任何编译器甚至bothers执行 C 的添加子句 - 等等。目的是生成有关此 C 子句及其(有意或无意)从 C++ 中遗漏的相关事实的有用目录。那么,我们走吧!


我已经在迷宫中找到了一些关于这方面的重要资料,并且我想我已经对此有了相当全面的总结。我将其发布为答案,因为它似乎解释了 C 子句的(在我看来非常误导)意图以及 C++ 不继承它的事实。如果我发现更多支持材料或情况发生变化,这将随着时间的推移而发展。

这是我第一次尝试总结一个非常复杂的情况,即使对于许多语言架构师来说,这似乎也定义不明确,所以我欢迎关于如何改进这个答案的澄清/建议 - 或者如果有人有更好的答案,只是一个更好的答案。

最后,一些具体的评论

通过模糊相关的线程,我找到了 @tab 的以下答案 - 并且非常赞赏其中包含的(具有启发性,如果不是决定性的)GCC 和工作组缺陷报告的链接:StackOverflow 上的按选项卡回答 https://stackoverflow.com/a/19807355

GCC 链接包含一些有趣的讨论,并揭示了委员会和编译器供应商的大量混乱和相互冲突的解释 - 围绕以下主题union member structC 和 C++ 中的 s、双关语和别名。

最后,我们链接到主要事件 - 另一个 BugZilla 线程,错误 65892 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892,包含一个极其有用的讨论。特别是,我们找到了两个关键文档中的第一个:

C99 中添加的行的由来

C提案N685 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n685.htm是关于可见性的附加条款的起源union类型声明。有些人声称(参见 GCC 线程 #2)完全误解了“共同初始序列”余量,N685 确实是旨在允许放宽“公共初始序列”的别名规则structTU 内的 s 意识到某些union包含上述实例struct types,正如我们从这句话中可以看到的:

建议的解决方案是要求联合声明可见 是否可以通过公共初始序列(如上所示)使用别名。 因此,如果需要,以下 TU 提供了这种别名:

union utag {
    struct tag1 { int m1; double d2; } st1;
    struct tag2 { int m1; char c2; } st2;
};

int similar_func(struct tag1 *pst2, struct tag2 *pst3) {
     pst2->m1 = 2;
     pst3->m1 = 0;   /* might be an alias for pst2->m1 */
     return pst2->m1;
}

从 GCC 的讨论和下面的评论(例如 @ecatmur 的评论)来看,该提案 - 似乎强制要求推测允许任何别名使用struct在某些内部有某个实例的类型union对此 TU 可见 -似乎受到了很大的嘲笑并且很少被实施.

很明显,在不完全削弱许多优化的情况下满足对附加条款的这种解释是多么困难 - 几乎没有什么好处,因为很少有编码员会想要这种保证,而那些想要的人可以打开fno-strict-aliasing(国际海事组织指出了更大的问题)。如果实施,这项津贴更有可能让人们出局并与其他声明进行虚假互动。unions,而不是有用。

C++ 中省略该行

继此以及我在其他地方发表的评论之后,@Potatoswatter 在这个答案中 https://stackoverflow.com/a/19805106指出:

C++ 中故意省略了可见性部分,因为它被广泛认为是可笑且无法实现的。

换句话说,看起来 C++ 故意避免采用这个添加的子句,可能是因为它被广泛认为是荒谬的。在要求对此进行“记录”引用时,Potatoswatter 提供了有关该帖子参与者的以下关键信息:

参与讨论的人基本上都是“记录在案”的。 Andrew Pinski 是一位铁杆 GCC 后端人员。 Martin Sebor 是一名活跃的 C 委员会成员。 Jonathan Wakely 是一名活跃的 C++ 委员会成员和语言/库实现者。该页面比我能写的任何内容都更加权威、清晰和完整。

Potatoswatter 在上面链接的同一个 SO 线程中得出结论,C++ 故意排除了这一行,对指向公共初始序列的指针没有留下特殊处理(或者最多是实现定义的处理)。与任何其他指示相比,它们的治疗将来是否会被具体定义,还有待观察;与我下面关于 C 的最后一节相比。但目前,它还不是(IMO,这很好)。

这对于 C++ 和实际的 C 实现意味着什么?

所以,N685 的邪恶线路……”cast除了’...我们回到假设指向公共初始序列的指针在别名方面并不特殊。仍然。值得确认的是,如果没有它,这一段在 C++ 中的含义是什么。好吧,上面的第二个 GCC 线程链接到另一个 gem:

C++ 缺陷 1719 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1719。该提案已达DRWP状态:“DR 问题,其解决方案反映在当前工作文件中。该工作文件是标准未来版本的草案”-cite https://social.msdn.microsoft.com/Forums/sqlserver/en-US/700569a7-18d3-4ddd-af0b-62bfe5aaf4d1/what-is-the-fastest-way-to-find-a-defect-in-the-c-standard-core-language-defect-report?forum=vcgeneral。这要么是 C++14 之后的事情,要么至少是在我这里的最终草案之后 (N3797) - 并提出了重要的是,在我看来,重写本段的措辞具有启发性, 如下。我将我认为重要的变化加粗,并且{这些评论}是我的:

在标准布局中与活跃成员的联盟 {“活动”表示union实例,而不仅仅是输入}(9.5 [类.联盟]) 结构体类型的T1,允许read {以前的“检查”}非静态数据成员m 另一位工会成员的结构体类型的T2假如m是的一部分 共同的初始序列T1 and T2. [Note:读取易失性对象 通过非易失性左值具有未定义的行为(7.1.6.1 [dcl.type.cv])。 ——尾注]

这似乎澄清了旧措辞的含义:对我来说,它说任何特别允许的其中‘双关语’union member struct必须完成具有共同初始序列的操作通过实例父母的union- 而不是基于类型structs(例如,指向它们的指针传递给某个函数)。这个措辞似乎排除了任何其他解释,a laN685。我想说,C 最好采用这个。嘿嘿,说到这里,请看下文!

结果是 - 正如 @ecatmur 和 GCC 票证中很好地证明的那样 - 这使得such union member struct根据 C++ 中的定义,以及实际上在 C 中的定义,与任何其他 2 个正式不相关的指针一样,遵循相同严格的别名规则。能够读取非活动的公共初始序列的显式保证union member struct现在的定义更加明确,不包括模糊且难以想象的繁琐的强制“可见性”尝试过由 N685 为 C 编写。根据这个定义,主要编译器的行为符合 C++ 的预期。至于C?

C 中此行的可能反转/C++ 中的澄清

同样值得注意的是,C 委员会成员 Martin Sebor 也希望用这种精美的语言来解决这个问题:

马丁·塞博尔 2015-04-27 14:57:16 UTC如果你们中有人能解释其中的问题,我愿意写一篇论文并将其提交给 WG14 并请求更改标准。

马丁·塞博尔 2015-05-13 16:02:41 UTC上周我有机会与克拉克·尼尔森讨论这个问题。 Clark 过去一直致力于改进 C 规范的别名部分,例如在 N1520 中(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1520.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1520.htm)。他同意,就像 N1520 中指出的问题一样,这也是一个值得 WG14 重新审视和解决的突出问题。”

Potatoswatter 鼓舞人心地得出结论:

C 和 C++ 委员会(通过 Martin 和 Clark)将尝试达成共识并敲定措辞,以便标准最终能够说出其含义。

我们只能希望!

再次强调,欢迎所有进一步的想法。

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

union '双关语'结构带有“公共初始序列”:为什么 C (99+) 而不是 C++ 规定了“联合类型的可见声明”? 的相关文章

随机推荐

  • 定期将数据从 mexFile 发送到 MATLAB

    我现在正在开发一个完全编写的数据采集工具 在 MATLAB 中 我用 MATLAB 写这个东西是我同事的愿望 以便他们可以扩展和修改它 该软件需要从两个连接的 USB 摄像头抓取照片 这些相机的 API 是用 C 编写的并记录在案 gt H
  • 在父级单击时触发事件,但在子级单击时不触发事件

    如果我有一个绝对定位的父 div 然后有一个具有较高 z index 且相对定位的子 div 有没有办法仅在父 div 被单击而不是内部 div 时才注册单击事件 相关jsFiddle http jsfiddle net Bt5HA 更新了
  • 通过将参数传递给 codeigniter 中的构造函数来加载库

    我正在使用代码点火器 我在 code igniter 中定义了一个库 并期望在其构造函数中包含一个参数 这是我的库代码 My Library Code Test lib php
  • strcpy 传递初始化的空指针 c [重复]

    这个问题在这里已经有答案了 我正在尝试以下代码 int main char yo yo char whaddup NULL strcpy whaddup yo 我遇到了段错误 在这里完成 C 菜鸟 其他地方说我应该初始化whaddup作为一
  • EF4 + MVVM - 在 ViewModel 中公开实体?

    我尝试过模型 视图 视图模型的一些不同实现 并且经常遇到我不确定正确的继续方法的情况 我知道 MVVM 的目标之一是将视图与应用程序逻辑解耦 以便可以在没有视图的情况下测试逻辑 将逻辑放入不依赖于 View 的 ViewModel 中可以解
  • 下载 Azure Web 应用程序?

    我刚刚开设了一个免费的 Azure 试用帐户 并通过各种表格创建了一个测试 Web 应用程序 但是 我想使用 Visual Studio 2015 在本地编辑源文件 是否可以下载注册期间生成的文件 如果可以 如何下载 谢谢你的帮助 您可以使
  • 如何将可变宽度的浮动元素水平居中?

    如何将可变宽度的浮动元素水平居中 编辑 我已经使用包含的div对于浮动元素并指定width对于容器 然后使用margin 0 auto 对于容器 我只是想知道是否可以在不使用包含元素的情况下完成 或者至少不需要指定width对于包含元素 假
  • 编写拼字游戏的算法

    我正在研究一个类似填字游戏的问题 但我不知道如何设计算法 例如 字典里有 汽车 苹果 等词 黑板上给出了 app 一词 有像 l e c r 这样的字母用于造词 所以算法的任务是生成存储在字典中的正确单词 app gt lapp gt le
  • 如何检查字符串是否为数字 Julia

    一直在互联网上搜索试图弄清楚这一点 尝试过isnumeric 但这仅适用于AbstractChar 我宁愿不用tryparse如果可能的话 但如果这是唯一的解决方案 那就这样吧 如果是的话 为什么还没有实现检查字符串是否为数字的函数 我发现
  • BasicAuth、OAuth 和 XAuth 之间有什么区别?

    最近我听说 Twitter 将关闭 Twitter API 上的基本身份验证 并转向 OAuth 所以我想知道BasicAuth OAuth 和XAuth 之间有什么区别 每个 Auth 的优点和缺点是什么 xAuth 是 OAuth 的简
  • 如何将Rtools\bin添加到R中的系统路径

    我正在运行一个闪亮的应用程序https github com MikeJSeo SAM https github com MikeJSeo SAM以及访问它的代码 install packages c samr matrixStats GS
  • Google Analytics Gtag 多个 Analytics 帐户跟踪 ID

    据我所知 谷歌现在似乎正在逐步淘汰analytics js 转而使用他们的标签管理器 如何为多个分析帐户触发 Google Analytics 新的 gtag 跟踪代码 像这样的事情
  • ggplot:根据用户定义的颜色按组划分颜色点

    我试图定义 ggplot 中绘制的点组的颜色 我改编了这篇文章的代码 根据定义的颜色代码为 ggplot 点着色 https stackoverflow com questions 9827193 color ggplot points b
  • NuSOAP 和数组响应

    我有 NuSOAP 网络服务器 server gt register getMembersEvents array date gt xsd string array Events gt tns Events urn my false rpc
  • R:如何读取列线图来预测所需的变量

    我正在使用 Rstudio 我使用函数创建了列线图nomogram从包装中rms使用以下代码 从示例代码复制文档 http www inside r org packages cran rms docs nomogram library r
  • 如何删除闪亮的renderUI中的输入?

    在我闪亮的应用程序中 我有一个使用 renderUI 的动态输入 这工作得很好 程序的另一部分捕获滑块的输入 当应用程序状态发生变化时 例如 当按下 更新模型 按钮时 我仍然需要显示 使用具有类似标签的滑块 但由于它们是 新的 因此需要将值
  • 如何延迟 html 文本的显示,直到加载背景图像精灵?

    这是我想使用 jQuery 控制的一些示例代码 黑色页面背景上的白色按钮背景 ul class buttons li class button displays a href products Products and Services f
  • 连接语句省略条目

    使用 Unix 2 6 18 194 el5 我遇到一个问题 该连接语句省略了匹配中的值 索引 我发现这些值在 11 90 之间 大约 350 万个条目 并且我尝试查找外来字符 但我可能忽略了某些内容 尝试使用 cat v 来查看隐藏字符
  • 雾化T的.Net Collection?

    我正在寻找是否有一个预先存在的 Net 哈希集类型 实现适合原子化一般类型 T 我们有大量相同的对象用于序列化源 需要原子化以节省内存 A Dictionary
  • union '双关语'结构带有“公共初始序列”:为什么 C (99+) 而不是 C++ 规定了“联合类型的可见声明”?

    背景 通过以下方式讨论类型双关的大多数非或实现定义的性质union通常引用以下位 此处通过 ecatmur https stackoverflow com a 31557852 2757035 https stackoverflow com