MISRA-C:2012年规则10.8“被投射到更广泛类型”的警告

时间:2017-11-25 22:38:39

标签: c misra

我得到规则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类型。像这样思考,警告对我来说似乎不自然。

3 个答案:

答案 0 :(得分:1)

  

为什么检测到警告?

让我们看看

void Fucntion(unsigned char isSwitchOn) {
  unsigned short switchMask = 0U;
  switchMask |= (unsigned short)(isSwitchOn & 1U) << 1;
  1. isSwitchOn,排名低于1U,通过通常的算术转换(C11§6.5.103)到类型{{1} }匹配unsigned

  2. 的类型 计算了
  3. 1U,结果类型为isSwitchOn & 1U

  4. 广告unsigned已应用于(unsigned short)结果 - 此步骤似乎很奇怪。 这是规则10.8的MISRA-C警告。没有必要演员。 复合类型 unsigned不必要地缩小为unsigned

  5. unsigned short结果已准备好进行转移,整数促销将在(unsigned short)的每个操作数上执行。因此,如果<<(unsigned short)会提升为int或可能unsigned。我们假设USHRT_MAX > INT_MAX

  6. 现在发生了int的转变。结果是类型int

  7. int已应用于int

  8.   

    此外,此代码是否会导致问题?

    我在这个的情况下没有看到,导致问题的演员是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发布了一个答案,解释了代码会发生什么以及错误的原因。至于如何解决它,你必须重写它。有两个问题:

  • 您正在使用字符类型作为布尔值,然后您还在算术中使用该字符类型,在促销后而不是在它们之前转换类型。据说这是为了摆脱额外的分支。
  • 您正在使用C的本机整数类型,它可以具有任何大小。这不是推荐的做法,违反了MISRA-C:2012 Dir 4.6。摆脱这些类型并使用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标准 - 不会在任何地方进行隐式促销。

更多信息:Implicit type promotion rules