使用 size_t 初始化循环变量时的整数下溢

Integer Underflow when initializing for loop variable with size_t

本文关键字:整数 下溢 变量 循环 size 初始化 使用      更新时间:2023-10-16

我正在运行下面的代码示例,最初尝试向后打印一个字符数组,其中count表示数组中的字符数。每次我运行 for 循环时,i并没有启动count - 1而是初始化为一些非常大的数字。但在循环之外,i 被正确地启动为 4。我无法解释为什么会发生这种情况。

size_t count {5};
size_t i {count - 1UL}; // i is initalized to 4
for(size_t i {count - 1}; i >= 0UL; --i) {
std::cout << i << std::endl;
} // infinite loop, i is initalized to 18446744073709141874

"无符号"整数没有符号,并且始终为非负数。 如果您在i = 0--i,那么您将获得最大值std::size_t.

请改为执行以下操作:

// iterates from (count - 1) to 0
for (std::size_t i = count; i--;)

那么这是如何工作的呢?i--是后缀递减运算符,它返回i的先前值。 这样,循环条件实际上是将count, ..., 1与零进行比较,而在循环中我们得到count - 1, ..., 0.

这个成语的一个更通用的版本有时被称为-->运算符:

// iterates from (high - 1) to low
for (std::size_t i = high; i-- > low;)

首先,外部作用域中的i未使用且带有阴影,其次,无符号整数始终大于或等于0。只要打开编译器警告,就可以让编译器检测到这些警告:

<source>:7:38: error: comparison of unsigned expression >= 0 is always true [-Werror=type-limits]
7 |     for(std::size_t i {count - 1}; i >= 0UL; --i) {
|                                    ~~^~~~~~
<source>:5:17: error: unused variable 'i' [-Werror=unused-variable]
5 |     std::size_t i {count - 1UL}; // i is initalized to 4
|

溶液:

for (unsigned long long i = 4ull; i != -1ull; --i) {
std::cout << i << 'n';
}

std::size_t是无符号整数类型。因此,类型的值永远不能为负数。

重写循环,例如

std::size_t i {count - 1};
do
{
std::cout << i << std::endl;
} while ( i-- );