【问题标题】:"Use of a signed integer operand with a binary bitwise operator" - when using unsigned short“使用带二进制位运算符的有符号整数操作数” - 使用无符号短时
【发布时间】:2018-10-28 04:09:27
【问题描述】:

在下面的 C sn-p 中检查是否设置了 16 位序列的前两位:

bool is_pointer(unsigned short int sequence) {
  return (sequence >> 14) == 3;
}

CLion 的 Clang-Tidy 给我一个“使用带二进制位运算符的有符号整数操作数”警告,我不明白为什么。 unsigned short 还不够无符号吗?

【问题讨论】:

  • 听起来像个错误。
  • It's getting fixed in JetBrains CLionclang-tidy bug 36961 中有一个 2018 年的讨论,但尚未修复。
  • 我联系了 Perforce 支持,要求对此问题进行澄清。让我们看看他们的回复。 (Perforce 是由 clang-tidy 实现的标准的维护者,在 CLion 中再次使用。)

标签: c clion clang-tidy


【解决方案1】:

The code for this warning 检查位运算符的 either 操作数是否有符号。引起警告的不是sequence,而是14,您可以通过在末尾附加u 使14 无符号来缓解问题。

(sequence >> 14u)

这个警告很糟糕。正如Roland's answer 所述,CLion 正在解决这个问题。

【讨论】:

  • 哇...只是哇...我想知道为什么它不抱怨提升为signed intsequence
  • @AnttiHaapala 这是一个很奇怪的检查我同意
  • 我接受了这个答案,因为它使警告消失了,而另一个没有:)
  • 发出“警告消失”并不总是好的。在某些情况下(例如这种情况),这是错误的警告,而不是您的代码。不要盲目相信警告。相反,试着去理解他们,然后决定谁错了。
【解决方案2】:

clang-tidy 中有一个名为hicpp-signed-bitwise 的检查。此检查遵循 HIC++ 标准的措辞。那个标准is freely available 说:

5.6.1。不要使用带符号操作数的位运算符

在某些情况下,将带符号操作数与位运算符一起使用会受到未定义或实现定义的行为的影响。因此,位运算符只能用于无符号整数类型的操作数。

HIC++ 编码标准的作者误解了 C 和 C++ 标准的意图,并且有意或无意地关注操作数的 type 而不是 value操作数。

clang-tidy 中的检查正是实现了这个措辞,以符合那个标准。该检查是not intended to be generally useful,其唯一目的是帮助那些程序必须符合 HIC++ 标准中的一条愚蠢规则的可怜人。

关键点是,根据定义,不带任何后缀的整型文字属于int 类型,并且该类型被定义为有符号类型。 HIC++ 现在错误地断定正整数文字可能是负数,因此可能调用未定义的行为

为了比较,C11 标准说:

6.5.7 移位运算符

如果右操作数的值为负数或大于或等于提升的左操作数的宽度,则行为未定义。

这个措辞是经过精心挑选的,强调正确操作数的很重要,而不是它的类型。它还涵盖了值过大的情况,而 HIC++ 标准只是忘记了这种情况。因此,在 HIC++ 中说 1u << 1000u 是可以的,而在 HIC++ 中说 1 << 3 不是。

最好的策略是明确禁用这个单一检查。有several bug reports for CLion 提到了这一点,它正在那里得到修复。


2019 年 12 月 16 日更新:我问 Perforce 这个确切措辞背后的动机是什么,以及措辞是否是故意的。这是他们的回应:

我们参与创建 HIC++ 标准的 C++ 团队查看了您提到的 Stack Overflow 问题。

简而言之,在 HIC++ 规则中引用对象类型而不是值是一种有意选择,以便更轻松地自动检查代码。对象的类型总是已知的,而值则不知道。

  • HIC++ 规则通常旨在“可判定”。强制执行该类型可确保始终可以进行可判定的检查,即。直接在使用运算符的地方或将有符号类型转换为无符号的地方。
  • 基本原理明确提到“可能的”未定义行为,因此合理的实现可以排除:
    • 常量,除非确实存在问题,并且,
    • 提升为有符号类型的无符号类型。
  • 因此,对于 CLion,最佳操作是在提升之前将检查限制为非常量类型。

【讨论】:

  • 潜在的问题是当负值向右移动时 - CPU 是在前面加上 0(之前什么都没有)还是 1(保持负值)?
  • @Pnemonic 是的,这是未定义行为的另一个领域。但这与 HICPP 检查无关,它是关于具有允许负值的类型具有可能为负的值之间的混淆。
  • 要禁用 CLion 中的规则,请转到文件 > 设置/首选项 > 编辑器 > 检查,然后在右侧窗格中选择 Clang-Tidy。在选项下,在标记为“逗号分隔的启用和禁用检查列表”的字段中,写一个逗号,然后-hicpp-signed-bitwise,然后按确定。
  • @mic 感谢您的解决方法。但这不是一个适当的解决方案。如果我在我的个人 IDE 副本中禁用该规则,这也不会阻止其他人感到困惑。因此,唯一明智的做法是告诉分销商这个错误检查(在这种情况下是 JetBrains,以及更上游的 Clang-Tidy)来解决这个问题。
【解决方案3】:

我认为整数提升会导致警告。对于带符号的算术表达式,小于 int 的操作数被扩展为整数。所以你的代码实际上是return ( (int)sequence >> 14)==3;,这会导致警告。试试return ( (unsigned)sequence >> 14)==3;return (sequence & 0xC000)==0xC000;

【讨论】:

  • 在阅读这个问题时,这也是我的想法......但是在提交我自己的答案之前弹出了(当前接受的)其他答案,这让我相信奥利弗是对...C11/6.3.1.1p2 是你的引文,顺便说一句
猜你喜欢
  • 1970-01-01
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-16
  • 2016-12-08
  • 1970-01-01
相关资源
最近更新 更多