3

I'm really confused.

uint8_t hash[20];
uint32_t u;

// Setting hash to some value here...

u = *(uint32_t*) hash;

This *(uint32_t*) hash causes a warning:

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

I think it's something wrong in typecasting, but I'm not sure, because I don't clearly know on how *(type*) var way of typecasting actually works. It seem to point on an object with an asterisk inside too. I am confused, that's the thing which forces me to ask a question about that. Especially I'd like to know how type* differs from *(type*). This may be a lot of help to get rid of this warning. Thanks in advance.

2501
  • 25,460
  • 4
  • 47
  • 87
Duosora
  • 83
  • 1
  • 1
  • 8

1 Answers1

1

You are not allowed to interpret an object trough an incompatible pointer as you do:

*(uint32_t*) hash;

Doing that will cause problems with alignment, endianness and violating strict aliasing which will cause undefined behaviour.

What happens is, you interpret the first four bytes of the array hash as an unsigned 32 bit integer.

 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

If your byte array is encoding little endian 32 bit unsigned integer, this is the portable, byte-order independent way of extracting:

#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
2501
  • 25,460
  • 4
  • 47
  • 87
  • 1
    Thank you for much help! I didn't knew that it's illegal operation. – Duosora Nov 03 '14 at 12:09
  • 1
    The strict aliasing rule is not about endiannes (although this can be a problem) but since aliasing types is not allowed by the spec, the compiler will make assumptions that may well prove invalid leading to obscure bugs. You can avoid this by using the -fno-strict-aliasing flag to your compile. – doron Nov 03 '14 at 12:54
  • @doron You should not do that. Other problems listed will still cause undefined behaviour. And please don't downvote a correct answer. – 2501 Nov 03 '14 at 12:56
  • The answer is not correct because even if you account for endianness breaking the strict aliasing rule will still cause problems. It is purely about the compiler making invalid assumptions and incorrectly reordering operations that should not br reordered. – doron Nov 03 '14 at 13:03
  • @doron Endianes and alignment are separate problems from strict aliasing which deals with violating aliasing. I hope now that you know, that I know what I'm talking about, you can remove the downvote. Evereone of us on SO is, hopefully, trying to improve the knowledge base. You are invited to contribute and edit the answer. This is not a competition. – 2501 Nov 03 '14 at 13:06