There was some interesting discussion around the following code, and I thought I would write it up here.
// Part I: int i = 0x01234567; int* pi = &i; char* pc = pi; // Part II: char c = 0x80; int* pi = &c;
Now, code in Part I is fine, while code in Part II has a problem. The C standard (C99) maintains that:
- ints are 4-byte aligned
- chars are 1-byte aligned
- data memory are byte addressable
- casting misaligned pointer types results in undefined operation
This means that a char* can address any data (such as an int) while the reverse may not be true. In the particular case above this means that while any int* can be converted to a char* (and back again), a random char* may not be convertible to an int*.
Even though an int* can be casted into a char*, notice that for big/little-endians, the byte orders are different so care should be taken when using this type of cast.
Now, for a little more depth, why is it that an arbitrary char* cannot be converted into an int*?
Most current CPUs are byte-addressable, meaning that each memory address points to an 8-bit block of memory cells. Many CPU instructions that operate on data stored in memory allow the data to have a size larger than 1 byte and would attempt to access the memory to read up to the size of the data type (e.g. 8 byte floating point operations). Data are naturally aligned if the starting address can be expressed as multiples of power of 2. For example 0x8 is aligned to 2,4… (See here for a full definition)
Some CPUs (x86 for example) can read misaligned data by performing multiple memory accesses and piecing together the data (for example half of the float from 1 access and the other half from another). Many CPUs however (such as MIPS, IA-64 etc) will not read data that are misaligned and any attempt raises a bus error (SIGBUS on POSIX), so if you cast a char* to int* and the start address of the new int* is not aligned, then any 4-byte aligned access to that location fails with bus error.