- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
背景
通过 union
讨论类型双关的大多数未定义或实现定义的性质通常引用以下位,这里通过@ecatmur ( https://stackoverflow.com/a/31557852/2757035 ),关于标准布局的豁免 struct
s 具有成员类型的“共同初始序列”:
C11 (6.5.2.3 Structure and union members; Semantics):
[...] if a union contains several structures that share a common initial sequence (see below), and if the union object currently contains one of these structures, it is permitted to inspect the common initial part of any of them anywhere that a declaration of the completed type of the union is visible. Two structures share a common initial sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.
C++03 ( [class.mem]/16 ):
If a POD-union contains two or more POD-structs that share a common initial sequence, and if the POD-union object currently contains one of these POD-structs, it is permitted to inspect the common initial part of any of them. Two POD-structs share a common initial sequence if corresponding members have layout-compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.
这两个标准的其他版本有相似的语言;从 C++11 开始
使用的术语是标准布局而不是 POD。
由于不需要重新解释,这并不是真正的类型双关语,只是应用于union
的名称替换。成员(member)访问。 C++17 的提案(臭名昭著的 P0137R1)使用类似“访问就像另一个结构成员被提名”这样的语言来明确说明这一点。
但请注意粗体 - “ 任何可以看到完整类型 union 声明的地方 ” - C11 中存在的子句,但在 2003、2011 或 2014 年的 C++ 草案中没有任何地方(几乎完全相同) ,但后来的版本用新术语标准布局替换了“POD”)。无论如何,“可见声明union
”在任何 C++ 标准的相应部分中都完全没有 type bit。
@loop 和 @Mints97,在这里 - https://stackoverflow.com/a/28528989/2757035 - 显示这条线也是 在 C89 中不存在,首次出现在 C99 并从那时起一直使用 C(不过,再一次,永远不会过滤到 C++)。
围绕这个的标准讨论
[剪断 - 见我的答案]
问题
因此,我的问题是:
这是什么意思? 什么被归类为“可见声明”?该条款是否旨在缩小 - 或扩大 - 这种“双关语”定义行为的上下文范围? 我们是否认为 C++ 中的这种省略是非常刻意的? C++ 与 C 不同的原因是什么? C++ 是否只是从 C89 中“继承”了这一点,然后决定——或者更糟的是,忘记——与 C99 一起更新? 如果差异是故意的,那么 C 与 C++ 中的 2 种不同处理方式有什么优点或缺点? 它在编译或运行时有什么有趣的后果(如果有的话)? 例如,@ecatmur 在回复我在他的原始答案(如上链接)中指出这一点的评论中,推测如下。
I'd imagine it permits more aggressive optimization; C can assume that function arguments
S* s
andT* t
do not alias even if they share a common initial sequence as long as nounion { S; T; }
is in view, while C++ can make that assumption only at link time. Might be worth asking a separate question about that difference.
好吧,我在这里,问!我对有关此问题的任何想法都非常感兴趣,尤其是:(任一)标准的其他相关部分、委员会成员或其他受人尊敬的评论员的引述、可能已经注意到实际差异的开发人员的见解 - 假设任何编译器甚至费心强制执行 C 的附加条款 - 等等。目的是生成有关此 C 条款及其(有意或无意)从 C++ 遗漏的相关事实的有用目录。所以,我们走吧!
最佳答案
我已经通过迷宫找到了一些关于此的重要资源,并且我认为我已经对其进行了非常全面的总结。我将此作为答案发布,因为它似乎解释了 C 子句的(IMO 非常误导)意图以及 C++ 没有继承它的事实。如果我发现进一步的支持 Material 或情况发生变化,这将随着时间的推移而发展。
这是我第一次尝试总结一个非常复杂的情况,即使对于许多语言架构师来说,这似乎也没有明确定义,所以我欢迎关于如何改进这个答案的澄清/建议 - 或者如果有人有一个更好的答案。
最后,一些具体的评论
通过模糊相关的线程,我找到了@tab 的以下答案 - 非常感谢其中包含的(如果不是结论性的)GCC 和工作组缺陷报告的链接:answer by tab on StackOverflow
GCC 链接包含一些有趣的讨论,并揭示了部分委员会和编译器供应商的大量混淆和相互矛盾的解释 - 围绕 union
的主题。成员(member)struct
C 和 C++ 中的 s、双关语和别名。
最后,我们与主要事件相关联 - 另一个 BugZilla 线程,Bug 65892 ,包含 极有用的讨论。特别是,我们找到了两个关键文档中的第一个的方法:
C99 中添加行的原点
C proposal N685是关于 union
的可见性的附加条款的起源类型声明。通过某些声称(参见 GCC 线程 #2)是对“公共(public)初始序列”许可的完全误解,N685 确实是 旨在允许放宽“公共(public)初始序列”的混叠规则struct
在 TU 内知道一些 union
包含上述 struct
的实例类型 ,正如我们从这句话中看到的:
The proposed solution is to require that a union declaration be visible if aliases through a common initial sequence (like the above) are possible. Therefore the following TU provides this kind of aliasing if desired:
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;
}
struct
使用别名。类型在某些
union
中具有某些实例此 TU 可见 -
似乎受到了很大的 mock ,很少实现 .
fno-strict-aliasing
(IMO 表明存在更大的问题)。如果实现,此津贴更有可能将人们抓获并与
union
的其他声明进行虚假互动。 s,比有用。
The visibility part was purposely omitted from C++ because it's widely considered to be ludicrous and unimplementable.
The folks in that discussion are essentially "on the record" there. Andrew Pinski is a hardcore GCC backend guy. Martin Sebor is an active C committee member. Jonathan Wakely is an active C++ committee member and language/library implementer. That page is more authoritative, clear, and complete than anything I could write.
In a standard-layout union with an active member {"active" indicates a
union
instance, not just type} (9.5 [class.union]) of struct typeT1
, it is permitted to read {formerly "inspect"} a non-static data memberm
of another union member of struct typeT2
providedm
is part of the common initial sequence ofT1
andT2
. [Note: Reading a volatile object through a non-volatile glvalue has undefined behavior (7.1.6.1 [dcl.type.cv]). —end note]
union
之间的“双关语”成员(member)struct
具有共同初始序列的 s 必须通过父级 union
的实例来完成。 - 而不是基于
structs
的类型(例如,指向它们的指针传递给某个函数)。这种措辞似乎排除了任何其他解释,如 N685。我会说,C 最好采用这种方法。嘿嘿,说起来,往下看!
union
成员(member)struct
s 根据 C++ 中的定义,实际上在 C 中,与任何其他 2 个正式无关的指针遵循相同的严格别名规则。 能够读取非事件的公共(public)初始序列的明确保证
union
成员(member)
struct
s 现在的定义更加明确,不包括 N685 为 C 尝试的模糊且难以想象的单调乏味的强制“可见性”。根据这个定义,主要编译器的行为与 C++ 的预期一致。至于C?
Martin Sebor 2015-04-27 14:57:16 UTC If one of you can explain the problem with it I'm willing to write up a paper and submit it to WG14 and request to have the standard changed.
Martin Sebor 2015-05-13 16:02:41 UTC I had a chance to discuss this issue with Clark Nelson last week. Clark has worked on improving the aliasing parts of the C specification in the past, for example in N1520 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1520.htm). He agreed that like the issues pointed out in N1520, this is also an outstanding problem that would be worth for WG14 to revisit and fix."
The C and C++ committees (via Martin and Clark) will try to find a consensus and hammer out wording so the standard can finally say what it means.
关于c++ - union 'punning' 结构 w/ "common initial sequence": Why does C (99+), 但不是 C++,规定 'visible declaration of the union type' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34616086/
最近,我开始学习 cuis-smalltalk,我没有意识到与 CLOS 相比,Smalltalk 的 OOP 有多么深刻和深入(我使用的是 Ruby)。我了解到 Smalltalk 是一个自己实现的
Maven存储库包含以下两个依赖项:org.apache.commons:commons-io:1.3.2和commons-io:commons-io:1.3.2。有什么区别,我应该在pom.xml中
我刚刚在我的 pom 文件中看到 Apache commons-collections 有两个不同的组 ID: commons-collections commons-collect
Windows 上的 Common Lisp 中是否有用于串行端口通信的库? 最佳答案 下面是一些使用 SBCL 外部函数 POSIX 调用实现串行通信的函数。它不如完整的库好,但我解决了根据此协议(
SBCL 64位,1.1.7 如果我想创建一个包并使用package:CL中的一些符号,我将创建一个像这样的包: (defpackage :foo (:import-from :cl
我正在忙着学习Common Lisp,并且正在寻找一种静态代码分析工具,该工具将帮助我开发更好的样式并避免陷入常见的陷阱。 我找到了Lisp Critic,看起来不错,但我希望有人可以推荐其他一些工具
我正在阅读《Practical Common Lisp》一书,在第 22 章第 284 页的脚注 5 中,我看到一段让我感到困惑的代码片段。 我知道变量list和tail有一个共同的列表结构,但我很困
我正在阅读 Practical Common Lisp ,并且对 Lisp 的 COPY-TREE 函数有疑问。 书中给出了调用的例子 (copy-tree '( '(1 2) '(3 4) '(5
我正在尝试使用 user guide 中的抓取示例运行 geb用于引入依赖项: $ cat my.groovy @Grapes([ @Grab("org.gebish:geb-core:0.9
这里一定有更好的方法,对吧? (format t "Enter your age: ~%") (defun age-case (age) (case age (1 (format t "Y
如何在 do 循环中绑定(bind)从函数返回的多个值? 以下显然是非常错误的,但是这样的事情可能吗? (do (((x y z) (3-val-fn) (3-val-fn))) ((equa
所以我正在学习 Lisp 做分数,这很棒。但是为什么这个相等性检查返回 NIL: * (= 0.2 1/5) NIL ...如果转换为 float 则返回 True第一的: * (=
是否可以“统计”一个文件并找到它的文件类型 - 常规或目录? 最佳答案 阅读关于 portable pathname library 的章节来自 Peter Seibel 的 Practical Co
我是 CL 的新手,正在使用 AllegroCL。我试图弄清楚如何组织我的源代码以满足以下要求: 我想阻止 src 代码包含我的测试套件。 我想以可移植的方式声明项目依赖项(src 和 test de
谁能告诉我最新的标准化 Common Lisp 的文档是什么(应该遵循各种实现的文档)?我问是因为我可以在网上找到很多关于 CL 的书都来自 90 年代,所以我想知道它们是否是最新的。我也来自于在 R
假设我必须定义一个名为foo 的函数。假设,为了定义它,我使用了一些辅助函数 foo1, foo2, foo3, ... 当我加载包含这些函数的文件时,我可以从顶层使用所有这些函数。相反,我只想从顶层
这拒绝编译。注释掉 (setf roll行让它编译。然而,(setf roll...本身在 REPL 中正确评估。 程序: ;; loop n times ; sum up number of hit
我目前正在学习 Common Lisp,并尝试将一些 JSON 发送到网络服务。我要发送的 JSON 以类似于以下的结构表示: ((:ITEMS ((:KEY . "value1") (:IGNO
我有一个带波浪号的目录名(作为字符串):~/projects . 我想得到它的完整路径:/home/user/projects .我怎么做 ? 目标是将它传递给 uiop:run-program ,这
我想从输入文件中读取一个字符串(用户可能修改也可能没有修改)。我想将此字符串视为使用固定数量的参数调用的格式指令。但是,我知道某些格式指令(特别是我想到的 ~/)可能会用于注入(inject)函数调用
我是一名优秀的程序员,十分优秀!