为什么我的工具在这里抛出MISRA错误?

问题描述

| 我该如何避免MISRA在以下代码中出现此错误?我尝试使用(unit16_t)进行铸造。但是后来它不允许显式转换。 从基本MISRA类型\“ unsigned char \”非法隐式转换为复杂表达式中的\“ unsigned int \”(MISRA C 2004规则10.1)  uint8_t速率= 3U;  uint8_t百分比= 130U;  uint16_t basic_units =比率*百分比;     

解决方法

        问题在于,整数促销类型“ \ int \”会默默地提升费率和百分比。因此,乘法是在有符号类型上执行的。 MISRA兼容代码是将代码重写为
 uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;
或按照MISRA的建议,立即将表达式的结果转换为其“基础类型”:
 uint16_t basic_units = (uint8_t)(rate * percentage);
编辑:澄清如下。   ISO 9899:1999 6.3.1.1 2      如果一个int可以代表原始类型的所有值,则该值将转换为int;   否则,它将转换为unsigned int。这些称为整数   促销活动。 MISRA-C提供的资料性文字:   MISRA-C:2004 6.10.3危险类型转换:      /-/      -算术运算中有符号性的更改:整数提升通常会导致两个无符号操作数产生(有符号)int类型的结果。例如,如果int为32位,则将两个16位无符号操作数相加将产生一个有符号的32位结果,但如果int为16位,则将产生一个无符号的16位结果。 我实际上不确定上面的第二行是否可以满足MISRA,第二个想法是我可能将MISRA 10.1与10.5混淆了,后者将立即强制转换为基础类型,但仅在某些按位方式的情况下操作员。 我用LDRA静态代码分析测试了这两行,并且没有抱怨(但是给出了一些不正确的,不相关的警告),但是LDRA在MISRA-C上的表现也很差。 无论如何,原始问题的问题在于,由于整数可以将uint8_t的所有值都表示为整数,所以费率和百分比都被整数提升隐式转换为带符号的int类型。所以变成
uint16_t basic units = (int)rate * (int)percentage.
为了防止这种情况,您必须显式键入。经过深思熟虑之后,我将继续上述两个步骤的第一行。     ,        对于乘法,在乘法之前执行隐式转换。也许在乘法关闭您的工具之前进行了明确的转换
uint16_t basic_units = (unsigned)rate * (unsigned)percentage;
结果
unsigned
的值应隐式转换为
uint16_t
,而没有警告。如果您的工具也选择为此做PITA,请尝试另一种显式转换:
uint16_t basic_units = (uint16_t)((unsigned)rate * (unsigned)percentage);
    ,        MISRA规则试图确保用于计算的“基础类型”与结果类型相同。为此,您可以强制转换其中一个或两个操作数:
uint8_t rate = 3U; 
uint8_t percentage = 130U;      
uint16_t basic_units = (uint16_t)rate * percentage;
在32位体系结构上,不进行强制转换的结果是可以的,但是,请考虑以下几点:
uint32_t rate =  ...;
uint32_t percentage = ...;
uint64_t basic_units = rate * percentage;
在32位架构上,即使目标类型为64位宽,操作也将以32位执行。如果速率和百分比足够大,则可能导致操作以32位换行,因此适合目标类型的数据将丢失。 不论目标平台上类型的大小如何,MISRA规则都试图使代码更安全。     ,        如果尝试使用C样式强制转换对操作数进行强制转换,则可能会给工具带来其他问题。因此,不要这样做:
uint16_t basic_units = (uint16_t)rate * (uint16_t)percentage;
您可能需要这样做:
uint16_t basic_units = static_cast<uint16_t>(rate) * static_cast<uint16_t>(percentage);