为什么unsigned类型没有下溢警告?

Why is there no underflow warning for unsigned type?

考虑以下代码:

unsigned int n = 0;
unsigned int m = n - 1;              // no warning here?
if (n > -1) {
    std::cout << "n > -1.\n";
} else {
    std::cout << "yes, 0 is not > -1.\n";
}

上面的代码在 if 条件 if (m > -1) 上产生警告,用于比较有符号和无符号整数表达式。我对此没有异议。困扰我的是前两个赋值语句。

unsigned int n = 0;
unsigned int m = n - 1;

我的想法是,编译器应该在第二次赋值时给我一个警告,因为它知道变量 n 是无符号的,第一行的值为 0 并且那里试图从零值中减去并将其分配给无符号类型。

如果第二次赋值后的下一行碰巧不同于 if 语句或类似的东西,那么相关代码可能已经漏掉了。

是的,在分配给 m 之前有一个收缩转换,是的,编译器不会抱怨它,Marshall Clow 在他的 C++Now 2017 Lightning Talk 中也提到了这一点(Fighting Compiler警告)。

short s = 3 * 6;
short s = integer * integer;
short s = integer;

那么,为什么编译器不能告诉我该代码中可能存在的下溢?

编译器:

原因是因为 if (n > -1) 永远不会为假,但 unsigned int m = n - 1; 是您可能想要编写的实际合法表达式。从 5 月 9 日开始,有一堆关于如何让你的有符号和无符号类型具有一致类型的规则,除了最终的默认条件

之外,所有这些都失败了

Otherwise, both operands shall be converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

由于无符号算术被明确定义为使用模运算,因此整个表达式是合法且定义明确的。他们仍然可以决定发出警告,但可能有足够多的遗留代码使用这样的技巧,这会导致太多误报。