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

Integer Underflow when initializing for loop variable with size_t

我是 运行 下面的代码示例,最初尝试向后打印字符数组,其中 count 表示数组中的字符数。每次我 运行 for 循环时,i 都没有被初始化为 count - 1 而是被初始化为一些非常大的数字。但是在循环之外,我被正确地初始化为 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

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

改为这样做:

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

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

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

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

std::size_t 是无符号整数类型。所以类型的值永远不会是负数。

像这样重写循环

std::size_t i {count - 1};

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

首先,外部作用域中的 i 未被使用且被遮蔽,其次,无符号整数始终大于或等于 0。只要你打开你的 compiler warnings:

你就可以让你的编译器检测到这些
<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';
}