为啥无符号类型没有下溢警告?

Posted

技术标签:

【中文标题】为啥无符号类型没有下溢警告?【英文标题】:Why is there no underflow warning for unsigned type?为什么无符号类型没有下溢警告? 【发布时间】:2016-04-04 15:28:28 【问题描述】:

考虑以下代码:

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 &gt; -1) 上产生一个警告,用于比较有符号和无符号整数表达式。我对此没有异议。困扰我的是前两个赋值语句。

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

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

如果第二次赋值后的下一行恰好与 if 语句或类似语句不同,则相关代码可能已通过。

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

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

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

编译器:

Clang 3.7/4.0 (-Wall -Wextra) GCC 5.3/7.1.1 (-Wall -Wextra -pedantic) 微软 C/C++ 19.00.23506

【问题讨论】:

您希望得到什么警告?您在 if 语句中收到的警告是 有符号和无符号整数表达式之间的比较,这不是 unsigned int m = n - 1; 中发生的情况 您是否尝试过使用 GCC 的 -Wall-Wextra 选项? @Plouff:是的,我已经将 -Wall -Wextra 与 GCC 一起使用。 【参考方案1】:

原因是因为if (n &gt; -1) 永远不会是假的,但unsigned int m = n - 1; 是您可能想要编写的实际合法表达式。从 5/9 开始,有很多关于如何让您的已签名无符号类型具有一致类型的规则,除了最终的默认条件外,所有这些规则都失败了

否则,两个操作数都应转换为无符号整数 type 对应于带符号整数的操作数的类型 输入。

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

【讨论】:

是否有免费的静态代码检查器会针对此类问题发出警告? “遗留代码”:它确实不一定必须是遗留代码,这是用新代码编写的完全有效的东西。另一方面,将无符号类型用于 bigint 类型的代码(您想要回绕的地方)或位域通常是错误的。

以上是关于为啥无符号类型没有下溢警告?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能用“无符号”来限定别名类型?

为啥减去无符号和有符号后符号不同?

[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]

[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]

[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]

[C/C++]_[初级]_[关于编译时出现有符号-无符号不匹配的警告-sizeof使用注意事项]