不应在指针类型和整数类型之间执行强制转换

ANU*_*KAR 3 c embedded pointers casting misra

我正在嵌入式 C 脚本中执行指针分配,如下所示:

uint32_T *a = (uint32_T *) (4096U); 
Run Code Online (Sandbox Code Playgroud)

基本上,我需要a指向地址位置4096(十进制)

我收到标题中指定的 MISRA 警告(我使用 Code Composer Studio 的 MISRA C:2004 检查器)。

我该如何解决这个警告?

PS:uint32_T是一个typedefunsigned long

Lun*_*din 6

这是一种 MISRA-C 规则本身不要太认真 - 该规则是建议性的,主要是为了迫使程序员三思而后行,然后再做有潜在危险的事情。

整数到指针的转换有很多陷阱:

  • 结盟。
  • 指针和整数之间的不同大小或表示。
  • 陷阱表示,包括硬件异常和无效地址。
  • 类型兼容性问题和严格的指针别名。

普通程序员通常不知道以上所有内容。如果不是,这种整数到指针的转换可能是危险的。

您必须事先知道所指向的地址是有效的,并且使用所选择的类型取消引用它是有意义的。例如,如果您知道在该内存地址处有一个 32 位硬件寄存器,那么通过uint32_t*指针取消引用就完全没问题了。

您还必须知道给定系统的指针格式。在 32 位系统上,它们通常只是 32 位地址。在 8/16 位 CPU 等较小的系统上,您可能有不同的指针类型,大小在 16 到 24 到 32 位之间,这使事情变得更加复杂。

总结:如果您知道自己在做什么,则可以忽略此建议性 MISRA-C 规则。


您的代码的其他问题:

  • 不要使用自制的整数类型,使用 stdint.h。如果您坚持使用 C90,那么定义与 stdint.h 中名称相同的类型并使用它们。
  • 不使用volatile就从内存地址转换为指针几乎肯定是错误的。编译器不知道那里存储了什么,如果您不volatile限定指针,可能会做出奇怪的假设和不正确的优化。如果它是硬件寄存器或 NVM 内存,它可能会随时更改,并且也必须volatile出于这个原因。

更正后的代码应该是: volatile uint32_t *a = (volatile uint32_t*)4096U;