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

问题描述 投票:1回答:2

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

uint32_T *a = (uint32_T *) (4096U); 

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

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

如何解决此警告?

PS:uint32_Tunsigned long的typedef

c pointers casting embedded misra
2个回答
2
投票

这是一种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;


0
投票

出于MISRA追求的确切原因,我在这样的演员被禁止的环境中工作。但是,在特定区域中,这种类型的转换非常普遍并且遵循特定的目的(即访问内存映射的硬件,尤其是在嵌入式微控制器等环境中)。

我设法使所有相关方面(主管,质量工程,需求工程等)都同意,该规则基本上适用并且要遵守,但是由于特殊的需要,对于特殊领域,该规则是允许的。即我得到了“空白通行证”,可以忽略这些警告,并且可以信任自己决定何时提供(如果我将其记录在案)。当然,这也意味着在其他情况下不要忽略它。

因此,这没有解决如何在代码中修复它的问题,但是它确实回答了在MISRA代码检查器是制作公认软件的重要部分的环境中如何避免麻烦的问题。

© www.soinside.com 2019 - 2024. All rights reserved.