取消引用类型惩罚指针将破坏严格别名规则[-Wstrict-aliasing]

时间:2014-11-03 11:58:30

标签: c++

我真的很困惑。

uint8_t hash[20];
uint32_t u;

// Setting hash to some value here...

u = *(uint32_t*) hash;

*(uint32_t*) hash会发出警告:

Dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]

我认为在类型转换中出现了问题,但我不确定,因为我并不清楚*(type*) var类型转换的实际工作方式。它似乎指向一个内有星号的物体。我很困惑,这是迫使我提出问题的事情。 特别是我想知道type**(type*)的区别。这可能是摆脱这个警告的很多帮助。 提前谢谢。

1 个答案:

答案 0 :(得分:1)

您不能像以下那样通过不兼容的指针解释对象:

*(uint32_t*) hash;

这样做会导致对齐,字节序和违反严格别名的问题,这会导致未定义的行为。

当您将数组哈希的前四个字节解释为无符号32位整数时,会发生什么。

 uint32_t* p = ( uint32_t* )hash ;  //cast must be there, pointer p is not valid 
 uint32_t u = *p ;  //dereference the pointer, this is undefined behaviour

如果你的字节数组是编码小端32位无符号整数,那么这是一种可移植的,无字节顺序的提取方式:

#include <stdint.h>
#include <limits.h>

uint8_t h[] = { 3 , 2 , 1 , 0 } ;  //1*3 + 256*2 + 65536*1 + 16777216 * 0
uint32_t a = 0 ;

for( size_t i = 0 ; i < sizeof( a ) ; i++ )
{
    a = a | (  h[i] << ( CHAR_BIT*i ) ) ;
}

printf("%u" , a ) ;  //66051