我想我真的在问:别名是“传递”吗?如果编译器知道A可能是别名B,而B可能是别名C,那么肯定它应该记住A可能因此别名C.也许这个“明显的”传递逻辑不是必需的吗?
一个例子,为了清楚起见。对我来说,最有趣的例子是严格别名问题:
// g++ -fstrict-aliasing -std=c++11 -O2
#include <iostream>
union
{
int i;
short s;
} u;
int * i = &u.i;
int main()
{
u.i = 1; // line 1
*i += 1; // line 2
short & s = u.s;
s += 100; // line 3
std::cout
<< " *i\t" << *i << std::endl // prints 2
<< "u.i\t" << u.i << std::endl // prints 101
;
return 0;
}
g ++ 5.3.0,在x86_64(但不是clang 3.5.0)上给出了上面的输出,其中*i
和u.i
给出了不同的数字。但是他们应该提供完全相同的数字,因为i
定义为int * i = &u.i;
且i
不会更改。
我有一个理论:当'预测'u.i
的值时,编译器会询问哪些行可能会影响u.i
的内容。这显然包括第1行。第2行,因为int*
可以为联盟的int
成员添加别名。第3行也是如此,因为任何可能影响一个联盟成员(u.s
)的东西都会影响同一联盟的另一个成员。但是在预测*i
时,它没有意识到第3行会影响int
的{{1}}左值。
这个理论看起来合理吗?
我觉得这个例子很有趣,因为我没有任何演员。我设法通过任何演员来打破严格别名。
答案 0 :(得分:5)
在C ++中未定义从union的非活动成员读取。 (它在C99和C11中是合法的。)
所以,总而言之,编译器不需要假设/记住任何东西。
Standardese:
N4140§9.5[class.union] / 1在联合中,最多一个非静态数据成员可以随时处于活动状态,也就是说,任何时候最多一个非静态数据成员的值都可以存储在一个联合中。
答案 1 :(得分:1)
只允许从最后用C ++写入的union成员中读取。
只允许在类似的&#39;之间使用工会外的别名。类型(详情请参阅this Q/A)和char
/ unsigned char
。只允许通过char
/ unsigned char
为其他类型设置别名,但不允许通过其他类型对char
/ unsigned char
进行别名。如果允许后者,那么所有对象都必须被视为可能别名任何其他对象,因为它们可能是传递别名的#39;就像你通过char
/ unsigned char
描述一样。
但是因为情况并非如此,编译器可以安全地假设只有类似“&#39;”的对象。类型和char
/ unsigned char
互为别名。