I encountered a strange problem when casting and modifying pointers on a 32bit embedded system (redbee econotag running contiki OS to be specific).
uint32_t array[2];
array[0] = 0x76543210;
array[1] = 0xfedcba98;
uint8_t* point = ((uint8_t*)array)+1;
printf("%08x \n", *(uint32_t*)point );
output on my computer:
98765432
output on embedded device:
10765432
My computer behaves as I expect it to, the embedded device however seems to wrap around when it reaches the end of the word. Why does this happen?
The
*
expression in this statement invokes undefined behavior: it violates aliasing rules and may do unaligned access.Because of the
+1
you do an unaligned access of a 32-bit value, i.e. the address is not a multiple of four.x86 works independently of alignment, because its roots go all the way back to 8-bit machines (maybe performance is slightly worse).
ARM requires alignment (as do many other processors), so 32-bit values should be placed at addresses that are a multiple of four bytes. Various bad things may happen if this isn't the case (wrong values, faults). For the array the compiler takes care of that, but when you explicitly cast the pointer you force it to violate alignment.
With this code, you break the strict aliasing rule: the object pointed by
point
is accessed by an lvalue expression that hasuint32_t
type.This leads to an undefined behavior, so anything can happen.
Your target "redbee econotag" is stated as an ARM7 which has ARMv4 architecture. ARMv4 doesn't provide unaligned memory access like an ARMv7 or an intel machine.
Quoting from ARM's documentation:
EDIT: please note that the body of this answer is made irrelevant by the comments it prompted
The theory of the other answers is fine, but probably doesn't help you. The actual problem is that you wrote:
When you should have written something such as
because you need to increment the pointer as a pointer to an appropriate type (so that the increment operation will add the size of an element), before you cast it to something else.
But one might ask if you really intend to have a byte pointer to a 32-bit value. Perhaps you do intend to access it in bytewise fashion (beware that the byte ordering will vary between systems!). Or perhaps you really intended for point to be a pointer to a 32-bit value which is in turn a pointer to an 8-bit value somewhere else...