编译器警告(等级 2)C4146
一元负运算符应用于无符号类型,结果仍为无符号类型
无符号类型只能保留非负值,因此一元减号 (否定) 在应用于无符号类型时通常没有意义。 操作数和结果都是非负数。
备注
表示负整数文本时,值前面的 -
将解析为一元反数运算符。 编译器在分析数值后应用运算符。 如果数值适合无符号整数类型的范围,但不适合相应的有符号整数类型,编译器会将该值解释为无符号。 无符号值由一元求非运算符保持不变。
尝试表示最小值 int
-2147483648 或最小值 long long
-9223372036854775808 时,通常会发生此警告。 这些值不能分别写为 -2147483648 或 -9223372036854775808ll。 原因在于编译器在两个阶段中处理表达式:首先,它会分析数值,然后应用求非运算符。 例如,当编译器分析 -2147483648 时,它将遵循以下步骤:
计算数值 2147483648。 因为它大于最大值
int
2147483647,但仍适合unsigned int
,2147483648 的类型是unsigned int
。一元减号应用于无符号值,且结果为无符号,也就是 2147483648。
结果的无符号类型可能会导致意外行为。 如果在比较中使用了结果,则可以使用无符号比较,例如,当另一个操作数是 int
时。
可以使用 <limits.h>
的 INT_MIN
或 LLONG_MIN
,或者 C++ 等效项 <climits>
,避免出现 C4146。 这些值具有有符号类型。
/sdl
(启用附加安全检查)编译器选项会将此警告升级为错误。
示例
以下示例演示编译器生成警告 C4146 时可能发生的意外行为:
// C4146.cpp
// compile with: /W2
#include <iostream>
void check(int i)
{
if (i > -9223372036854775808ll) // C4146
std::cout << i << " is greater than the most negative long long int.\n";
}
int main()
{
check(-100);
check(1);
}
在此示例中,编译器认为 -9223372036854775808ll 是无符号的,即使文本具有 ll
后缀,并且应用求非运算符。 为了进行 <
比较,编译器以无提示方式将有符号的 i
提升为 unsigned long long int
。 预期的第二行 1 is greater than the most negative long long int
,不会打印,因为 ((unsigned long long int)1) > 9223372036854775808ull
为 false。
若要修复该示例,请包括 <climits>
并更改 -9223372036854775808ll 为 LLONG_MIN
。