Cal*_*ius 15 c strict-aliasing
以下面的代码片段为例:
*pInt = 0xFFFF;
*pFloat = 5.0;
Run Code Online (Sandbox Code Playgroud)
由于他们是int和float指针,编译器将假定他们不这样做别名,例如可以交换.
现在让我们假设我们用这个来加强它:
*pInt = 0xFFFF;
*pChar = 'X';
*pFloat = 5.0;
Run Code Online (Sandbox Code Playgroud)
因为char*允许别名,它可能指向*pInt,所以赋值*pInt不能超出赋值*pChar,因为它可以合法地指向*pInt并将其第一个字节设置为'X'.类似地pChar可以指向*pFloat,*pFloat在char赋值之前不能移动赋值,因为代码可能打算通过重新分配来取消先前字节设置的效果*pFloat.
这是否意味着我可以通过编写和读取char*来为重新排列和其他严格的别名相关优化创建障碍?
在编译器无法知道指针变量是否为另一个指针的别名时,指针别名通常很有意义.与编译位于与调用者不同的翻译单元中的函数的情况一样.
void func (char* pChar, float* pFloat)
{
*pChar = 'X';
*pFloat = 5.0;
}
Run Code Online (Sandbox Code Playgroud)
这里的pFloat分配确实不能在分配之前排序pChar,因为编译器不能扣除pChar不指向同一位置的分配pFloat.
但是,在面对这种情况时,编译器可以(并且可能会)添加运行时检查以查看地址是否指向重叠内存.如果他们这样做,那么代码必须按给定的顺序排序.如果不是,则可以重新组织和优化代码.
这意味着只有在指针实际上为别名/指向重叠内存的情况下才会获得类似内存屏障的行为.如果没有,那么关于指令排序的所有赌注都将被取消.所以这可能不是你应该依赖的机制.