通常,在C中,在左值上使用一元&
运算符会产生一个指针,使得在底层对象的生命周期内的任何时间,将一元*
应用于指针将产生一个相当于原始的左值。这种行为本质上是&
运算符的含义。
然而,在gcc中,通过将&
应用于联合成员而产生的指针似乎在任何明显的时间段内都不可用。例如,给定:
struct s1 {int x;};
struct s2 {int x;};
union u {struct s1 v1; struct s2 v2;};
int test(union u *u1, union u *u2)
{
struct s1 *p1 = &u1->v1;
if (p1->x)
{
struct s2 *p2 = &u2->v2;
p2->x = 5;
}
p1 = &u1->v1;
return p1->x;
}
int test2(void)
{
struct s2 s = {1};
union u u1;
u1.v2 = s;
return test(&u1,&u1);
}
gcc将为test1生成返回1而不是5的代码,除非
采用-fno-strict-aliasing。请注意p1->v1.x
和p2->v2.x
两个部分相同的Common Initial Sequence,一个完整的union定义
在访问它们的任何地方都可见,并使用左值p1->v1
在p2->v2.x
的写入和p1->v1.xp
的后续读取("检查")之间。如果将address-of运算符应用于union成员并不能保证产生一个指针,该指针可用于检查由此识别的左值,那么运算符是什么意思?