I just found an insidious and disconcerting characteristic of the uVision3 ARM compiler V3.12a. I have inherited C code to migrate to the ARM processor. This C code uses unsigned char pointers quite liberally to pass the address of data back and forth. The code, of course, casts these generic unsigned char pointers to various data types to access the underlying data. I have found that if the unsigned char point happens to be pointing at a odd address and it is cast to a short type pointer (e.g., "*(SHORT*)p"), the compiler will resolve the address the previous even address. For a simplistic example, if the address of unsigned char *p happens to be 0x5 and the following code is executed:
unsigned char *p; ... *(unsigned short*)p = 0;
"The casts override the compiler's tracking of types and their alignment requirements. That is, after all, exactly what a C cast does. It tells the compiler, "I'm the programmer; I know what I'm doing; do what I say". If the programmer is doing the wrong thing with his casts, it's hardly the compiler's fault. Misalignment detection is handed by the memory subsystem on the ARM, rather than by the core itself. If your ARM has ARM's MMU or "Memory Protection Unit" (MPU), then those peripherals will generate an interrupt to the core when they detect a misaligned transfer. You could write an interrupt handler to detect this condition, do a couple of aligned transfers, and patch the data back together (just as x86s or PPC does in hardware). But of course you'll lose a fair amount of speed if the misaligned accesses are common. On the other hand, this solution will cover all of the uses." However, it appears that the compiler is not blindly obeying the programmer when he uses a cast, instead it is 'correctly' aligning the pointer to prevent an alignment exception occurring. The result of this is that memory is being silently trashed. In my opinion this is undesirable - I'd far rather my program crashed straight away than ran incorrectly.