【发布时间】:2018-08-14 16:34:47
【问题描述】:
使用这些定义:
struct My_Header { uintptr_t bits; }
struct Foo_Type { struct My_Header header; int x; }
struct Foo_Type *foo = ...;
struct Bar_Type { struct My_Header header; float x; }
struct Bar_Type *bar = ...;
说这段C代码对吗(“case one”):
foo->header.bits = 1020;
...实际上与此代码语义不同(“案例二”):
struct My_Header *alias = &foo->header;
alias->bits = 1020;
我的理解是它们应该是不同的:
案例一认为分配无法影响 Bar_Type 中的标头。它仅被视为能够影响其他 Foo_Type 实例中的标头。
情况二,通过强制通过通用别名指针进行访问,将导致优化器意识到所有可能包含
struct My_Header的类型的所有赌注都关闭。它将与通过任何指针类型的访问同步。 (例如,如果您有一个Foo_Type指向实际上是一个Bar_Type,它可以通过标头访问并可靠地找出它所具有的 - 假设这是标头位可以告诉您的内容。)
这依赖于优化器没有变得“智能”并将案例二变成案例一。
【问题讨论】:
-
嗯。我在这里看不到任何别名...
-
@EugeneSh。混叠是隐含的。通过 foo 写入标题,通过 bar 读取它们,看不到更新。
-
指向结构的成员并不违反任何规则;您仍在通过指向
My_Header的指针访问My_Header,因此您并没有真正为任何东西添加别名。 -
据我从C11 6.5.2.3p6 了解到,如果
Bar_Type和Foo_Type不能通过联合成员访问进行访问,编译器的行为就好像Bar_Type和Foo_Type没有即使它们实际上重叠,也会在内存中重叠。 -
@HostileFork:编译器识别从另一种类型的左值明显派生的指针可能用于访问后一种类型的对象的情况的能力是实施质量问题。基本原理中没有任何内容表明他们认为编译器编写者会以规则为借口故意忽略这种推导可见的情况。从标准的角度来看,使用结构指针的代码和直接访问成员的代码具有等效(未定义)的行为,但质量编译器应该同时处理两者。
标签: c language-lawyer strict-aliasing