Let's say that both int
and float
are 4-byte aligned. According to ISO C99 6.3.2.3 p.7:
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the pointed-to type, the behavior is undefined.
According to this, the following code should not invoke UB:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i = 7;
float *f = (float *) &i;
exit(0);
}
I noticed that GCC is not always good at catching strict aliasing rules violation attempts but here in can correctly warn that dereferencing *f will break will break strict-aliasing rules what is illegal according to 6.5 p. 7:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
$ gcc -Wall -fstrict-aliasing -Wstrict-aliasing=2 so1.c -Wcast-align
so1.c: In function ‘main’:
so1.c:7:2: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
so1.c:7:9: warning: unused variable ‘f’ [-Wunused-variable]
So does it mean that this code may invoke UB only when *f will be dereferenced and it's 100% correct in current shape?
EDIT:
One more thing - would this cast be also legal if float had a different size from int but alignment would still be the same for both types? I think yes because this is what C standard says but I don't understand why alignment is the most important here and not size. Why does alignment matters when converting pointers and only when dereferencing?