精度损失(分配)

Loss of precision (assignment)

本文关键字:分配 损失 精度      更新时间:2023-10-16

我的代码(我代码的某些部分)得到以下警告:

# 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:从整数转换为指针[MISRA 2004年规则11.3]
  • 信息 734:精度损失(赋值)(32 位到 16 位)

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

有人可以告诉我这样做的正确方法....

这里的关键是你正在与你(大概)有严格规格的硬件接口。

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

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

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

    因此,您可以安全地忽略该注释。

  • "info"是不言自明的:宏建议您将每个寄存器位置视为一个 32 位字,但随后您尝试将该值塞入 16 位。

    一些可能性:

    • 这是错误的,每个寄存器实际上是 16 位;
    • getfreqmhz应返回uint32;或
    • 或者,根据对值范围的一些了解,您确定您正在执行的操作是有效的,然后您的强制转换方法就可以了。

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

  1. 您确定从PLL读取的值的最高16位为0。在这种情况下,请忽略警告(如果需要,也可以使用强制转换将其删除),因为您不感兴趣的高阶 0 将自动删除。
  2. 您对从 PLL 读取的整个 32 位值感兴趣。在这种情况下,M应该uint32能够包含所有这些数据。

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