I've recently read about type punning and strict aliasing in C. I believe the following attempt at type-punning violates the strict aliasing rule:
uint32_t x = 0;
float f = *(float *)&x;
In order to type-pun correctly, Wikipedia says "the strict alias rule is broken only by an explicit memcpy or by using a char pointer as a "middle man" (since those can be freely aliased)."
So, my first question is: does the following code violate the strict aliasing rule (or invoke undefined/unspecified behavior)? Several sources say this is legal and fine, while others say it's not:
uint32_t x = 0;
float f = *(float *)(char *)&x;
- If so, (how) could this code be fixed? (still using the same "char pointer as a 'middle man' " idea) Or would I have to instead use
memcpy
or a union? - If not, why? How would casting to
char*
and then tofloat*
be any "safer" than simply casting tofloat*
(or is safety not the issue)?
My second question regards endianness, since that also seems to come up when discussing type-punning.
If I malloc()
some memory for two different data types (assuming aligned properly), could reading one or the other have different results on different platforms? As an example:
float *p = malloc(sizeof(uint32_t) + sizeof(float)); // Allocating space for a uint32_t and a float
uint32_t *a = (uint32_t *)(char *)p;
float *b = (char *)p + sizeof(uint32_t);
// Use a and b, etc.
Could this change based on the endianness of the system? I'd assume not since I'm not using the value of a float read as an integer; the integer is being used as an integer and the float is being used as a float.
I'd still consider myself a beginner in C, so I'm guessing there are better ways to do things like this, maybe type-punning isn't necessary at all, so feel free to include alternate solutions in your answer. Thanks.