我得到规则10.8的MISRA-C警告: “基本无符号”类型(unsigned char)的复合表达式被强制转换为更宽的无符号类型“unsigned short”。
使用以下代码检测到此警告。
void Fucntion(unsigned char isSwitchOn) {
unsigned short switchMask = 0U;
switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;
为什么检测到警告? 此外,此代码是否会导致问题?
我认为表达式(isSwitchOn&amp; 1U)被转换为int类型并进行计算,结果被截断并存储为unsigned short类型。像这样思考,警告对我来说似乎不自然。
答案 0 :(得分:1)
为什么检测到警告?
让我们看看
void Fucntion(unsigned char isSwitchOn) {
unsigned short switchMask = 0U;
switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;
isSwitchOn
,排名低于1U
,通过通常的算术转换(C11§6.5.103)到类型{{1} }匹配unsigned
。
1U
,结果类型为isSwitchOn & 1U
。
广告unsigned
已应用于(unsigned short)
结果 - 此步骤似乎很奇怪。 这是规则10.8的MISRA-C警告。没有必要演员。 复合类型 unsigned
不必要地缩小为unsigned
。
unsigned short
结果已准备好进行转移,整数促销将在(unsigned short)
的每个操作数上执行。因此,如果<<
,(unsigned short)
会提升为int
或可能unsigned
。我们假设USHRT_MAX > INT_MAX
。
现在发生了int
的转变。结果是类型int
。
int
已应用于int
。
此外,此代码是否会导致问题?
我在这个的情况下没有看到,导致问题的演员是WET编程。如果结果是unsigned short
,那么移出的位就会丢失。
在转换后投射结果更有意义。 @Myst
unsigned switchMask
或使用
避免其他潜在警告switchMask |= (unsigned short)((isSwitchOn & 1U) << 1);
我认为表达式
switchMask = (unsigned short)(switchMask | ((isSwitchOn & 1U) << 1));
被转换为int类型并计算
不,表达式(isSwitchOn & 1U)
将转换为int类型并进行计算。
注意:(unsigned short)(isSwitchOn & 1U)
和unsigned char isSwitchOn
不是同一类型,这是可疑的。
答案 1 :(得分:0)
关于:
unsigned short switchMask = 0U;
此声明使用unsigned short int
unsigned int
关于:
switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;
此声明正在与unsigned short int
进行unsigned int
答案 2 :(得分:0)
Chux发布了一个答案,解释了代码会发生什么以及错误的原因。至于如何解决它,你必须重写它。有两个问题:
stdint.h
代替,这允许您编写确定性的可移植代码。现在有两种方法可以处理隐式类型的促销:要么让它们发生并随后投射 - 这通常是MISRA所喜欢的。或者你根本不让它们发生,通过在评估操作之前转换为宽的无符号类型,从而消除隐式提升。就MISRA而言,两者都应该没问题;我个人更喜欢后者。
固定代码如下:
// ok if 8/16 bit system only
void Function (bool isSwitchOn) {
uint16_t switchMask = ((uint16_t)isSwitchOn & 1U) << 1U;
或
// 32 bit system/fully portable code
void Function (bool isSwitchOn) {
uint32_t shift = (uint32_t)isSwitchOn & 1U;
uint16_t switchMask = (uint16_t) (shift << 1U);
请注意,这些示例应生成完全相同的机器代码。因此,您也可以在8位系统上使用完全可移植的版本。在给定的系统上,两者都符合MISRA-C标准 - 不会在任何地方进行隐式促销。