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++ 规定了“联合类型的可见声明”? 的相关文章

  • C# 打印问题(RichTextBox)

    我想打印我的 RichTextBox eintragRichTextBox 的内容 我现在有这个代码 private void druckenPictureBox Click object sender EventArgs e PrintD
  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • json.net自定义jobject反序列化

    我正在尝试使用 JsonConvert DeserializeObject string 将字符串反序列化为可与动态一起使用的 jobject 来动态访问 json 文档 但是我想避免知道文档的大小写 以便我可以输入 dynamic doc
  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 从模板切换传递的类型

    在 C 中是否可以检查传递给模板函数的类型 例如 template
  • 在开关中使用“goto”?

    我看到了一个建议的编码标准 内容如下Never use goto unless in a switch statement fall through 我不跟 这个 例外 案例到底是什么样的 这证明了goto 此构造在 C 中是非法的 swi
  • Gwan C#,如何获取HTTP标头?

    我需要它来重写 url 以了解我正在处理哪个友好的 url 用于用户代理和其他东西 EDIT public class Gwan MethodImplAttribute MethodImplOptions InternalCall exte
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 使用 LINQ 更新 IEnumerable 对象的简单方法

    假设我有一个这样的业务对象 class Employee public string name public int id public string desgination public int grade List
  • 将接口转换为其具体实现对象,反之亦然?

    在 C 中 当我有一个接口和几个具体实现时 我可以将接口强制转换为具体类型 还是将具体类型强制转换为接口 这种情况下的规则是什么 Java 和 C 中都允许这两个方向 向下转型需要显式转型 如果对象类型不正确 可能会抛出异常 然而 向上转换
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • ASP.NET MVC 路由:如何从 URL 中省略“索引”

    我有一个名为 StuffController 的控制器 具有无参数索引操作 我希望从表单中的 URL 调用此操作mysite com stuff 我的控制器定义为 public class StuffController BaseContr
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • 在 C#.NET 中安全删除文件

    在我正在做的一个项目中 我想为用户提供 安全 删除文件的选项 例如 用随机位或 0 覆盖它 在 C NET 中是否有一种简单的方法可以做到这一点 效果如何 你可以调用系统内部删除 http technet microsoft com en
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 为什么以下 C 程序会出现总线错误?

    我认为这是第一个失败的 strtok 调用 好久没写C了 有点不知所措 非常感谢 include
  • 来自 3rd 方库的链接器错误 LNK2019

    我正在将旧的 vc 6 0 应用程序移植到 vs2005 我收到以下链接器错误 我花了几天时间试图找到解决方案 错误LNK2019 无法解析的外部符号 imp 创建AwnService 52 在函数 public int thiscall
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan

随机推荐

  • 定期将数据从 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