精度损失(分配)

时间:2014-01-17 16:55:46

标签: c++ c lint

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

# 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被删除,但我认为这是不正确的想法。

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

2 个答案:

答案 0 :(得分:2)

这里的关键是您正在与您(可能)具有严格规格的硬件接口。

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

  • 该注释告诉您关于(volatile Uint32*)(ISS_PLL_BASE+MN2DIV)(在宏内部),您在其中形成一个整数的指针。

    在任何任意的C ++程序中,我都同意MISRA并说这是一个糟糕的形式,但是既然你指定了你知道的实际PLL位置,那对我来说似乎很好。我自己做。

    所以,你可以放心地忽略这个音符。

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

    一些可能性:

    • 这是错误的,每个寄存器实际上是16位;
    • getfreqmhz应返回uint32;或
    • 根据对值范围的一些了解,您确定知道您正在做什么是有效的,然后您的演员方法就可以了。

答案 1 :(得分:1)

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

  1. 您肯定知道从PLL读取的值的最高16位是0.在这种情况下,忽略警告(或者如果需要,可以使用强制删除它),因为您不感兴趣的高阶0 in会自动删除。
  2. 您对从PLL读取的整个32位值感兴趣。在这种情况下,M应该uint32能够包含所有这些数据。
  3. 关于从整数到指针的强制转换的第一个警告是针对托管代码,其中将整数转换为指针是没有意义的。在微控制器领域,当您尝试访问映射到固定地址的外设寄存器时,这非常有意义。由于您使用的是微控制器,请忽略该警告。