"使用带有二进制位运算符的带符号整数操作数" - 使用无符号短整型时

Sak*_*mon 34 c clion clang-tidy

在下面的C片段中,检查是否设置了16位序列的前两位:

bool is_pointer(unsigned short int sequence) {
  return (sequence >> 14) == 3;
}
Run Code Online (Sandbox Code Playgroud)

CLion的Clang-Tidy给我一个"使用带有二进制位运算符的有符号整数操作数"警告,我无法理解为什么.是unsigned short不是没有签名?

Rya*_*ing 42

此检查的代码似乎关心按位运算符的任一操作数是否已签名.它没有sequence引起警告,但是14,通过使14未签名的问题可以缓解这个问题.

(sequence >> 14u)
Run Code Online (Sandbox Code Playgroud)

  • 哇...哇...我想知道为什么它不抱怨升为`signed int`的`sequence`。 (3认同)
  • 让“警告消失”并不总是好的。在某些情况下(例如本例),错误的是警告,而不是您的代码。不要盲目相信警告。相反,尝试理解他们,然后判断谁错了。 (3认同)
  • @AnttiHaapala 这是一个非常奇怪的检查,我同意 (2认同)

Rol*_*lig 25

在 clang-tidy 中有一个名为 的检查hicpp-signed-bitwise。此检查遵循 HIC++ 标准的措辞。该标准是免费提供的,并说:

5.6.1. 不要将按位运算符与有符号操作数一起使用

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

HIC++ 编码标准的作者误解了 C 和 C++ 标准的意图,无意或有意地将注意力集中在操作数的类型而不是操作数的上。

clang-tidy 中的检查正是实现了这个措辞,以符合该标准。该检查的目的不是普遍有用,其唯一目的是帮助那些程序必须符合 HIC++ 标准的愚蠢规则的可怜人。

关键的一点是,根据定义,没有任何后缀的整数文字是 type int,并且该类型被定义为有符号类型。HIC++ 现在错误地得出结论,正整数文字可能是负数,因此可能会调用未定义的行为

为了进行比较,C11 标准说:

6.5.7 按位移位运算符

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

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

最好的策略是明确禁用此单一检查。CLion几个错误报告提到了这一点,并且正在那里修复。


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

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

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

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

  • 要在 CLion 中禁用该规则,请转到“文件”&gt;“设置/首选项”&gt;“编辑器”&gt;“检查”,然后在右侧窗格中选择“Clang-Tidy”。在“选项”下,在标有“启用和禁用检查的逗号分隔列表”的字段中,写入一个逗号,然后写入“-hicpp-signed-bitwise”,然后按“确定”。 (2认同)

小智 8

我认为整数提升会导致警告.小于int的操作数被扩展为整数,用于算术表达式,该算术表达式已签名.因此,您的代码可以有效地return ( (int)sequence >> 14)==3;提供警告.试试return ( (unsigned)sequence >> 14)==3;return (sequence & 0xC000)==0xC000;.

  • 在阅读此问题时,这也是我的想法……但是,在提交我自己的答案之前,另一个(当前接受的)答案突然出现,这使我相信奥利弗是正确的……[C11 / 6.3 .1.1p2](https://port70.net/~nsz/c/c11/n1570.html#6.3.1.1p2)是您的引用,顺便说一句 (2认同)