Clang-tidy-18 hicpp-signed-bitwise规则出现“使用有符号整数”误报?
问题:Clang-tidy hicpp-signed-bitwise检查的异常报错分析
用户配置了Clang-tidy的hicpp-signed-bitwise检查,开启IgnorePositiveIntegerLiterals选项后,运行无符号整数位运算代码仍收到错误提示。用户理解前两个错误源于8位值的隐式整数提升,但疑惑为何mytypeU32 & 1报错,而mytypeU32 << 2等运算无报错。
配置文件
# .clang-tidy --- FormatStyle: file WarningsAsErrors: '*' Checks: > -*, hicpp-signed-bitwise, CheckOptions: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals: true
示例代码
#include "stdint.h" #include "stdio.h" #include "inttypes.h" typedef uint8_t mytypeU8_t; typedef uint32_t mytypeU32_t; int main(void) { mytypeU8_t mytypeU8 = 0; mytypeU32_t mytypeU32 = 0; unsigned char testChar = 0; printf("%"PRIu8, testChar & 1); printf("%"PRIu8, testChar << 2); printf("%"PRIu8, (testChar << 2 ) | (testChar >> 2)); printf("%"PRIu8, mytypeU8 & 1); printf("%"PRIu8, mytypeU8 << 2); printf("%"PRIu8, (mytypeU8 << 2 ) | (mytypeU8 >> 2)); printf("%"PRIu32, mytypeU32 & 1); printf("%"PRIu32, mytypeU32 << 2); printf("%"PRIu32, (mytypeU32 << 2 ) | (mytypeU32 >> 2)); return 0; }
报错信息
test.c:15:22: error: use of a signed integer operand with a binary bitwise operator [hicpp-signed-bitwise,-warnings-as-errors] 15 | printf("%"PRIu8, (testChar << 2 ) | (testChar >> 2)); | ^~~~~~~~~~~~~~~~ ~ test.c:19:22: error: use of a signed integer operand with a binary bitwise operator [hicpp-signed-bitwise,-warnings-as-errors] 19 | printf("%"PRIu8, (mytypeU8 << 2 ) | (mytypeU8 >> 2)); | ^~~~~~~~~~~~~~~~ ~ test.c:21:35: error: use of a signed integer operand with a binary bitwise operator [hicpp-signed-bitwise,-warnings-as-errors] 21 | printf("%"PRIu32, mytypeU32 & 1); | ~ ^
原因分析与解决
1. 前两个错误的原因(8位无符号类型的位或运算)
unsigned char和uint8_t这类8位无符号类型,在参与位运算时会触发整数提升:由于int类型能容纳原类型的所有取值,这些8位值会被隐式转换为signed int。
testChar << 2和mytypeU8 << 2的结果都是signed int,后续和另一个提升后的signed int执行|运算时,就触发了hicpp-signed-bitwise对有符号操作数位运算的禁止规则,因此报错。
2. mytypeU32 & 1报错但mytypeU32 << 2不报错的核心差异
(1)mytypeU32 << 2不报错的原因
移位操作的检查逻辑核心是被移位的操作数类型:
mytypeU32是uint32_t,在32位平台上,uint32_t的取值范围超过signed int的最大值(2^31-1),因此整数提升时会转换为unsigned int而非signed int。- 移位位数
2是正整数字面量,开启IgnorePositiveIntegerLiterals选项后,检查会忽略有符号字面量作为移位位数的情况,因此不会触发错误。
(2)mytypeU32 & 1报错的原因
二元位运算(&/|/^)的检查逻辑会关注所有操作数的原始类型:
mytypeU32是uint32_t(无符号),而字面量1默认是signed int(有符号)。IgnorePositiveIntegerLiterals选项仅适用于两个有符号操作数之间的运算(其中一个是正整数字面量),但这里是无符号和有符号操作数的混合运算,该选项不生效,因此检查触发错误。
解决方法
要消除mytypeU32 & 1的错误,只需将字面量1显式声明为无符号类型:
printf("%"PRIu32, mytypeU32 & 1U);
对于前两个8位类型的位或错误,同样可以通过显式转换为无符号类型来避免整数提升为signed int:
printf("%"PRIu8, (unsigned)(testChar << 2) | (unsigned)(testChar >> 2));
内容的提问来源于stack exchange,提问作者Slav
相关产品推荐
相关产品推荐

