This is the kind of MISRA-C rule not to take too serious in itself - the rule is advisory and is mostly there to force programmers to think twice and study, before they do something which is potentially dangerous.
There are numerous pitfalls in integer to pointer conversions:
- Alignment.
- Different size or representation between pointers and integers.
- Trap representations, including hardware exceptions and invalid addresses.
- Type compatibility issues and strict pointer aliasing.
The average programmer is typically not aware of all of the above. And if they aren't, such integer to pointer conversions may be dangerous.
You must know in advance that the address pointed at is valid, and it makes sense to de-reference it with the picked type. For example, if you know that there is a 32-bit hardware register at that memory address, it's perfectly fine to de-reference through a uint32_t*
pointer.
You must also know the pointer format for the given system. On 32 bit systems they are typically just 32 bit addresses. On smaller system like 8/16 bit CPUs, you may have different pointer types with sizes between 16 to 24 to 32 bits, making things more complicated.
Summary: if you know what you are doing, you can ignore this advisory MISRA-C rule.
Other issues with your code:
- Don't use homebrewed integer types, use stdint.h. If you are stuck with C90, then define types with the same name as those in stdint.h and use those.
- Casting from a memory address to a pointer without using
volatile
is almost certainly wrong. The compiler doesn't know what's stored there, and may make strange assumptions and incorrect optimizations if you don't volatile
-qualify the pointer. And if it's a hardware register or NVM memory, it may change at any time, and must be volatile
for that reason too.
Corrected code should be: volatile uint32_t *a = (volatile uint32_t*)4096U;