【问题标题】:Loss of precision (assignment)精度损失(分配)
【发布时间】:2014-01-17 16:55:45
【问题描述】:

我的代码(我的代码的某些部分)低于警告:

# define MN2DIV                    0x14                     
# define PLL_BASE_ADDRESS          0x481C5000                
# define ISS_PLL_BASE              (PLL_BASE_ADDRESS+0x140)                  
# define    M_PLL                 (volatile Uint32*)(ISS_PLL_BASE+MN2DIV)           

uint16 getfreqmhz(void)
{          
    uint16 M;          
    M= *M_PLL;           
} 
  • 注释 923:从 int 转换为指针 [MISRA 2004 Rule 11.3]
  • 信息 734:精度损失(赋值)(32 位到 16 位)

我尝试通过以下方式转换: M= (uint16)*M_PLL ;
上述更改的原因是警告 734 已删除,但我认为这不是正确的想法。

谁能告诉我这样做的正确方法....

【问题讨论】:

  • 是的。:( ..你能告诉我任何可以修复 MISRA 警告的工具..
  • 我感觉很糟糕。

标签: c++ c lint


【解决方案1】:

这里的关键是您正在与您(可能)具有严格规范的硬件进行交互。

如果 MISRA 是一款通用静态分析器,它就无法识别您的微控制器环境中的唯一保证。您正在做 C++ 作为标准不太喜欢的事情,因为它们在(比如说)PC 上没有意义。但是,如果有足够的关于硬件及其接口的信息,你的代码在实践中可以是完全安全的;如果是这样,您可以忽略/禁止这些诊断。

  • 注释告诉您(volatile Uint32*)(ISS_PLL_BASE+MN2DIV)(在宏内部),您可以在其中从整数形成指针。

    在任何任意 C++ 程序中,我都同意 MISRA 并说这是不好的形式,但是由于您指定了您知道的实际 PLL 位置,所以对我来说似乎很好。我自己做。

    因此,您可以放心地忽略该注释。

  • “信息”是不言自明的:宏建议您将每个寄存器位置视为一个 32 位字,但随后您试图将该值填充到 16 位中。

    一些可能性:

    • 这是错误的,每个寄存器实际上是 16 位;
    • getfreqmhz 应该返回一个 uint32;或
    • 或者你肯定知道你在做什么是有效的基于对值范围的一些知识,然后你的演员方法就可以了。

【讨论】:

  • 另一种可能性是宏中的转换应该真正转换为 uint16 ...
  • @PlasmaHH:这就是我错误地扩展“要么这个错误”的结果!
【解决方案2】:

您正在从 PLL 读取 32 位值并将其存储在 16 位变量中。有两种情况:

  1. 您肯定知道从 PLL 读取的值的最高 16 位为 0。在这种情况下,忽略警告(或根据需要使用强制转换将其删除),因为您不感兴趣的高阶 0 in 会自动删除。
  2. 您对从 PLL 读取的整个 32 位值感兴趣。在这种情况下,M 应该是 uint32 才能包含所有这些数据。

关于从整数转换为指针的第一个警告是针对托管代码,其中将整数转换为指针是没有意义的。在微控制器世界中,当您尝试访问映射到固定地址的外围寄存器时,这非常有意义。由于您似乎使用的是微控制器,因此请忽略该警告。

【讨论】:

  • 如果 OP 正在执行 MISRA 检查,那么我会假设他的应用程序是安全关键的。 MISRA 警告是有原因的,我认为忽略它们是一个非常糟糕的选择。
  • @JoeHass,如果微控制器数据表显示 SPI 状态寄存器位于地址 0x504 并且它是一个字节,那么写入 #define SPI_STATUS *(uint8_t *)0x504 然后在代码中使用 SPI_STATUS 就可以了。事实上,没有其他方法可以解决它。 MISRA 是为托管应用程序编写的。他们的一些规则可能仍然适用于独立世界,但肯定不是全部,正如您在该示例中看到的那样。
  • 实际上,一种解决方法:#define SPI_STATUS *((uint8_t *)0 + 504) 但那你就是在自欺欺人。
  • 也就是说,MISRA 本身对代码的保护过度。我相信 MISRA 假设程序员是一个对语言本身一无所知的砖头,并且有防止任何白痴破坏任何东西的规则。例如,如果您有uint16_t x = ...; uint8_t y = x >> 8;,即使x >> 8 的类型大于uint8_t,也绝对没有理由发出警告。请尽量不要盲目遵守任何规则(不仅仅是在编程中)。
  • 我支持我的声明...您忽略 MISRA 规则会危及您的职业生涯和那些依赖您代码的人的风险。请记住,关键代码需要由另一方进行验证……依靠这样的技巧会使验证变得更加困难。此外,您忽略了代码重用的可能性。如果您的“已知良好”代码与不同的架构一起使用,它可能会以不可预知的方式中断。如果您正在为玩具编写代码,请忽略警告。
猜你喜欢
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 2020-07-28
  • 2015-04-26
  • 1970-01-01
  • 2016-12-19
  • 1970-01-01
  • 2020-04-26
相关资源
最近更新 更多