strict aliasing
strict aliasing一文中将这些条文允许alias总结如下:
1.兼容类型(指相同类型?)或差别仅在于signed、unsigned、const、volatile的类型(比如 const unsigned long *和 long*)
2.聚合类型(struct或class)或联合类型(union)可以alias它们所包含的类型(比如 int 和 包含有int的结构体(包括间接包含))
3.字符类型(char *、signed char*、unsinged char*)可以 alias 任何类型的指针
4.[C++] 基类的类型(可能带有const、volatile等cv修饰)可以alias派生类的类型
float funky_float_abs (float *a)
{
unsigned int * temp = (unsigned int*) a;
temp &= 0x7fffffff;
return *(float*)temp;
}
在-O2的时候会出现问题,可以使用-fno-strict-aliasing来消除这个问题
有效的做法
Use a char or void pointer during the cast. These always alias to anything, so they are safe.
float funky_float_abs (float *a)
{
float temp_float = *a;
// valid, because it's a char pointer. These are special.
unsigned char * temp = (unsigned char *) a;
temp[3] &= 0x7f;
return temp_float;
}
Use memcopy. Memcpy takes void pointers, so it will force aliasing as well.
float funky_float_abs (float *a)
{
int temp_int i;
float temp_float result;
memcpy (&i, a, sizeof (int));
i &= 0x7fffffff;
memcpy (&result, &i, sizeof (int));
return result;
}
And while I'm at it: The next code has nothing to do with strict aliasing. It works in practice but it relies on undefined behaviour as well:
float funky_float_abs (float *a)
{
union
{
unsigned int i;
float f;
} cast_helper;
cast_helper.f = *a;
cast_helper.i &= 0x7fffffff;
return cast_helper.f;
}
linux内核编译时是加了
-fno-strict-aliasing这个参数的(内核编译时加V=1可以看到)
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
http://dbp-consulting.com/tutorials/StrictAliasing.html
http://blog.csdn.net/dbzhang800/article/details/6720141
http://hi.baidu.com/rsjdsibkwtnrxyr/item/b04e86dbdc8351de241f40cc
http://www.dutor.net/index.php/2012/07/gcc-strict-aliasing/