考虑下列源代码示例,它说明某些别名级别无法处理内部指针。有关内部指针的定义,请参见表 B–13。
struct foo { int f1; struct bar *f2; struct bar *f3; int f4; int f5; struct bar fb[10]; } *fp; struct bar struct bar *b2; struct bar *b3; int b4; } *bp; bp=(struct bar*)(&fp->f2);
weak、layout、strict 或 std 不支持该示例中的非关联化。在指针赋值 bp=(struct bar*)(&fp->f2) 之后,以下各对内存访问将访问相同的存储单元:
fp->f2 和 bp->b2 访问相同的存储单元
fp->f3 和 bp->b3 访问相同的存储单元
fp->f4 和 bp->b4 访问相同的存储单元
但是,使用选项 weak、layout、strict 和 std 时,编译器假定 fp->f2 和 bp->b2 不设定别名。由于 b2 的偏移为零,与 f2 的偏移(四字节)不同,并且 foo 和 bar 没有公共初始序列,因此编译器作出该假定。同样,编译器还假定 bp->b3 不将 fp->f3 作为别名,bp->b4 不将 fp->f4 作为别名。
因此,指针赋值 bp=(struct bar*)(&fp->f2) 将使编译器关于别名信息的假定不正确。这可能会导致不正确的优化。
请在进行以下示例中显示的修改之后尝试编译。
struct foo { int f1; struct bar fb; /* Modified line */ #define f2 fb.b2 /* Modified line */ #define f3 fb.b3 /* Modified line */ #define f4 fb.b4 /* Modified line */ int f5; struct bar fb[10]; } *fp; struct bar struct bar *b2; struct bar *b3; int b4; } *bp; bp=(struct bar*)(&fp->f2); |
在指针赋值 bp=(struct bar*)(&fp->f2) 之后,以下各对内存访问将访问相同的存储单元:
fp->f2 和 bp->b2
fp->f3 和 bp->b3
fp->f4 和 bp->b4
通过检查前面的代码示例中显示的更改,您可以看到表达式 fp->f2 是表达式 fp->fb.b2 的另一种形式。由于 fp->fb 为 bar 类型,因此 fp->f2 访问 bar 的 b2 字段。此外,bp->b2 也访问 bar 的 b2 字段。因此,编译器假定 fp->f2 将 bp->b2 作为别名。同样,编译器假定 fp->f3 将 bp->b3 作为别名,fp->f4 将 bp->b4 作为别名。结果,编译器假定的别名与指针赋值产生的实际别名匹配。