【问题标题】:static analysis weird sign behavior with mixed C and C++ code混合 C 和 C++ 代码的静态分析奇怪的符号行为
【发布时间】:2019-07-22 14:58:20
【问题描述】:

在混合 C 和 C++ 程序中给出以下定义:

//in a C file.
uint8_t GetSize()
{
return (uint8_t)something;
}

//in the header of the C++ file.

public:
  MyClass(){};
private:
  uint8_t index_m;

以下两行都给了我一个静态工具(pc-lint)warning 573

void MyClass::IncrementWithRollOver(void)
{
        index_m = (index_m + 1) % GetSize(); // warning 573 : signed-unsigned mix with divide
}
void MyClass::DecrementWithRollOver(void)
{
        index_m = (GetSize() - 1 + index_m) % GetSize(); // warning 573 : signed-unsigned mix with divide
}

我尝试了很多投射,但没有一个可以帮助我摆脱这个警告,为什么?

        index_m = (index_m + 1U) % GetSize(); // this one works

        index_m = (GetSize() - 1U + index_m) % GetSize();// info 834: operator '-' followed by operator '+' could be confusing without parentheses [MISRA 2004 Rule 12.1, advisory]

        index_m = (uint8_t)(index_m + (uint8_t)1) % GetSize(); // warning 573 : signed-unsigned mix with divide, and: info 732: loss of sign (assignment) ('int' to 'uint8_t' (aka 'unsigned char')

        index_m = (uint8_t)(GetSize() - (uint8_t)1 + index_m) % GetSize(); // warning 573 : signed-unsigned mix with divide, and: info 834: operator '-' followed by operator '+' could be confusing without parentheses [MISRA 2004 Rule 12.1, advisory]

        index_m = (uint8_t)(index_m + (uint16_t)1) % GetSize(); // warning 573 : signed-unsigned mix with divide, and: info 732: loss of sign (assignment) ('int' to 'uint8_t' (aka 'unsigned char')

        index_m = (uint8_t)(GetSize() - (uint16_t)1 + index_m) % GetSize(); // warning 573 : signed-unsigned mix with divide, and: info 834: operator '-' followed by operator '+' could be confusing without parentheses [MISRA 2004 Rule 12.1, advisory]

... C 多么痛苦!

有什么快速解决方法?


读完cmets我也试过了,没成功

     index_m = (uint8_t)(index_m + (uint32_t)1) % GetSize(); // works

     index_m = (uint8_t)(GetSize() - (uint32_t)1 + index_m) % GetSize(); // info 834: operator '-' followed by operator '+' could be confusing without parentheses [MISRA 2004 Rule 12.1, advisory]

这让我摆脱了符号/无符号混合问题,但是这个“运算符'-'后跟运算符'+'”仍然很奇怪!

【问题讨论】:

  • 这是您应该使用int 或更大类型的部分原因。小于int 的所有内容都将转换为int/unsigned int 以进行内置操作。
  • 我也尝试过使用大于 uint8_t 的 uint16_t。和同样的警告。
  • 在 32 位机器中,int 将是 int32_t。如果您想要无符号,那么 uint32_t 将是内置运算符的最小类型。
  • 因为uint16_t 小于int(和unsigned int)...
  • 鉴于来自index_m = (GetSize() - 1U + index_m) % GetSize(); 的警告,您是否尝试过index_m = (GetSize() + index_m - 1U) % GetSize();

标签: c++ c static-analysis


【解决方案1】:

有什么快速解决方法?

最简单的是:

 index_m = (index_m + 1U) % GetSize(); // this one works

可以递增,但问题在于递减......

index_m = (GetSize() - 1U + index_m) % GetSize();// info 834: operator '-' followed by operator '+' could be confusing without parentheses [MISRA 2004 Rule 12.1, advisory]

请注意,这只是一条信息消息;不是警告。但无论如何,缺少括号的解决方案是添加括号:

index_m = ((GetSize() - 1U) + index_m) % GetSize();

或者,显然将操作顺序更改为 (GetSize() + index_m - 1U),如 cmets 中所述

【讨论】:

  • 不是我在 "index_m = (uint8_t)(index_m + (uint8_t)1) % GetSize();" 行中所做的?
  • @GuillaumeD 我改变了建议。
  • @GuillaumeD:注意1Uunsigned int(uint8_t)1 被提升为已签名的int
  • @JonathanLeffler 我最初有不同的建议。评论是关于那个
  • 我的评论是关于 Guillaume D 评论中的代码;它使用(uint8_t)1,这是一个签名的int 值。但是,如果您确信我的评论没有帮助(或“cmets 没有帮助”),请将其标记为“不再需要”,我会将我的懊恼隐藏在对其他问题和答案的 cmet 暴风雪中。
【解决方案2】:

在 C/C++ 中,小于int 的整数会提升为具有相同符号且与int 一样大的整数,只要您在操作中使用它们( +...)。

这是历史性的,有点令人困惑,但我猜最初的意图是限制溢出小整数计算的风险。

index_m + 1 中,index_m 将提升为unsigned int,然后符号与1 不匹配,即signed int

所以你必须在操作完成后cast(取决于警告级别)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 2012-07-01
    • 2010-11-11
    • 1970-01-01
    • 2011-10-11
    • 2017-12-20
    • 2013-08-16
    • 1970-01-01
    相关资源
    最近更新 更多