gcc (6.3.1 20170109) when compiling the following program
#include <stdio.h>
int main(int argc, const char *argv[]) {
unsigned char x[] = {0x66, 0x19};
printf("%i\n", ((short *)((char *)&x[0]))[0]);
return 0;
}
generates as warning:
pun.c: In function ‘main’:
pun.c:5:5: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
Shouldn't type aliasing allowed when using char
pointers?
Here’s what C11 (or at least the free draft N1570) has to say about aliasing:
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.
The character type exception means you can access any type via a char*
or unsigned char*
, but it doesn’t mean you can access a char*
via any type. short*
doesn’t meet the other criteria listed here for char*
, so this use is undefined behaviour.
Plus, you could break alignment requirements if that were allowed unconditionally:
short x[] = {1, 2};
char* alias = x;
printf("%i\n", *(short*)&alias[1]);