![]() |
1
2
您的两个结构不兼容,因为它们是不同的类型。您已经找到了“兼容类型”一章,该章定义了使两个结构兼容的原因。稍后,当您使用指向错误类型的指针访问这些结构时,将出现ub,这是6.5/7中的严格别名冲突。 解决这一问题的明显方法是:
现在,类型可以别名,因为
另一种方法是使用隐藏在C17 6.5.2.3/6中的“联合公共初始序列”的秘密特殊规则:
这将允许您在声明原始类型时使用它们。但在同一翻译单元的某个地方,您必须添加一个虚拟联合typedef才能使用上述规则:
你不需要实际使用这个联合的任何实例,它只需要在那里可见。这告诉编译器这两种类型可以别名,只要它们的公共初始序列是这样的。在您的例子中,它意味着函数指针,而不是后面的变量
编辑: 免责声明。常见的初始序列技巧显然有点争议,编译人员使用它做的事情比委员会预期的要多。在C和C++中可能不同。参见 union 'punning' structs w/ "common initial sequence": Why does C (99+), but not C++, stipulate a 'visible declaration of the union type'? |
![]() |
2
1
如果“严格的别名规则”(N1570 6.5P7)仅仅被解释为规定了事物可以别名的情况(这似乎是作者的意图,给出脚注88,说明“此列表的目的是指定对象可以或不可以别名的情况”),那么像您这样的代码就不应构成任何问题。LEM规定,在使用两种不同类型的lvalue访问对象的所有上下文中,所涉及的lvalue之一显然是从另一个lvalue派生而来的。 6.5p7唯一可行的方法是,如果涉及从其他对象新鲜可见派生的对象的操作被识别为对原始对象的操作。然而,何时承认这种派生的问题仍然是一个实施质量问题,并且认为市场比委员会更能判断什么东西是“质量”实施所必需的,以适合某些特定目的。 如果目标是编写能够在配置为符合脚注88明确意图的实现上工作的代码,那么只要对象没有别名,就应该是安全的。为了满足这一要求,可能需要确保编译器能够看到指针彼此相关,或者它们在使用时都是从一个公共对象新派生出来的。给定的,例如
每个指针都将在新派生的上下文中使用。
注意,如果代码是:
然后第二次使用
根据标准的作者,C的精神包括“信任程序员”和“不要阻止程序员做需要做的事情”的原则。除非有特殊的需要来处理一个不特别适合自己所做工作的实现的局限性,否则我们应该以适合自己目的的方式来针对那些支持C精神的实现。这个
|
![]() |
Xirema · 如何正确编写运算符的R值重载 7 年前 |
![]() |
Mário Feroldi · 在运行时调用代码中未调用的函数 7 年前 |
![]() |
chqrlie · 所有位0都可以是整数的陷阱表示吗? 7 年前 |
![]() |
Vincent · 打印零,但不基于该条件退出循环 7 年前 |
![]() |
Dror K. · 用%p打印空指针是未定义的行为? 7 年前 |
![]() |
Bite Bytes · C中允许这种函数调用吗 7 年前 |
![]() |
K J Gor · C中strncpy的内存混淆 8 年前 |