给定以下代码段
#include <inttypes.h>
uint8_t test(uint32_t foo)
{
if (foo > 0xFFFFFFFF)
{
return 0;
}
if (foo < 0)
{
return 0;
}
return 1;
}
使用gcc 12.2编译-Wall -Wextra
只得到以下警告:
warning: comparison of unsigned expression in '< 0' is always false [-Wtype-limits]
9 | if (foo < 0)
| ^
我不明白为什么第一行if (foo > 0xFFFFFFFF)
没有触发相同的警告。
尝试if (foo > UINT32_MAX)
不会触发任何编译器警告。
是bug还是特性?
这些警告不是语言规则强制要求的,由编译器供应商决定是否添加它们。gcc警告你关于第二个if
可以被认为是一种礼貌。由于这个原因,我认为我们不能认为这是一个bug,除非您可以在gcc中发现这个特定的特性。文档,这可能会改变我的看法。
我检查clang对于这些警告,当然它根本不警告你,至少没有那些标志:
https://godbolt.org/z/c7hbM3K5d
只有当你尝试-Weverything
时,它才会警告你这两种情况:
<source>:5:13: warning: result of comparison 'uint32_t' (aka 'unsigned int') > 4294967295 is always false [-Wtautological-type-limit-compare]
if (foo > 0xFFFFFFFF)
~~~ ^ ~~~~~~~~~~
<source>:9:13: warning: result of comparison of unsigned expression < 0 is always false [-Wtautological-unsigned-zero-compare]
if (foo < 0)
~~~ ^ ~
https://godbolt.org/z/9b9q13rTe
+1 forclang在我的书里。
如果你想在你的构建中看到这些警告,一定要使用特定的标志(-Wtautological-unsigned-zero-compare
和-Wtautological-type-limit-compare
),使用-Weverything
会太啰嗦,标记许多你不需要的情况,如在评论中提到的。
返回gcc,如果您使用更宽的类型进行比较,例如if (foo > 0xFFFFFFFF0)
,则会收到警告:
<source>:5:13: warning: comparison is always false due to limited range of data type [-Wtype-limits]
5 | if (foo > 0xFFFFFFFF0)
| ^
https://godbolt.org/z/Edvz7aq3b
我们可以假设他们忘记包括uint32_t
的最大值,这可能是一个错误,或者可能是警告实现关注类型而不是值,我们只能推测。如果你坚持让这个特殊的警告为UINT32_MAX
工作,你可以提交一个报告,或者至少得到它的结束,并找出这种行为的原因。