在倒数计数循环中使用size_t时的无限循环

AdH*_*nem 3 c loops size-t infinite-loop

所以我使用size_t而不是int在任何索引for循环中来防止负指数.但倒数时,这会导致溢出:

for (size_t i = 10; i >= 0; --i) {
    // Do something, f.ex. array[i] = i
}
Run Code Online (Sandbox Code Playgroud)

什么是防止这种情况的好方法?

  • int而代替?
  • 使用i == 0作为终止条件?(如果我需要0,这将无效)

我很感激任何反馈!

wil*_*ser 5

for (size_t i = 11; i-- > 0; ) {
    // Do something, f.ex. array[i] = i
}
Run Code Online (Sandbox Code Playgroud)

注意:问题以 value=10 开始循环(这很奇怪,但并非不可能)。我从11开始,但是第一次进入循环体时,它已经递减到10了。


chq*_*lie 5

从技术上讲,它不是溢出,因为它size_t是无符号类型,但它绝对是一个无限循环,因为终止条件始终为真。

无符号整数在 处递减时回绕011请注意,您的循环将在回绕发生之前运行次,而不是10.

在递减索引之前必须检查条件。使用比最大有效索引大一的初始值开始枚举可以提高视觉一致性并简化测试。

这是一个更正的版本,您可以看到 的初始值i是数组的元素数量:

int array[11];
for (size_t i = 11; i-- > 0; ) {
    // Do something, f.ex. array[i] = i
}
Run Code Online (Sandbox Code Playgroud)


Yan*_*hou 5

for (size_t i = 10; i <= 10; --i) // do something
Run Code Online (Sandbox Code Playgroud)

当溢出确实发生时,它将舍入到最大整数,因此条件将失败.


Vla*_*cow 2

最简单的方法是增加上限值。例如

const size_t N = 10;

for (size_t i = N + 1; i != 0; --i) {
    // Do something, f.ex. array[i-1] = i-1
}
Run Code Online (Sandbox Code Playgroud)

或者

const size_t N = 10;

for (size_t i = N + 1; i-- != 0; ) {
    // Do something, f.ex. array[i] = i
}
Run Code Online (Sandbox Code Playgroud)

一般情况下,当 i 可以等于存储在该类型的对象中的最大值时,size_t您可以使用以下技巧

#include <stdio.h>

int main( void )
{
    const size_t N = 10;

    for (size_t i = N, j = N; !( i == 0 && j == -1 ); j--)
    {
        i = j;
        printf( "%zu ", i );
    }

    printf( "\n" );
}
Run Code Online (Sandbox Code Playgroud)

否则你可以使用 do-while 循环。在这种情况下更合适。例如

size_t i = N;

do
{
    printf( "%zu ", i );
} while ( i-- != 0 );
Run Code Online (Sandbox Code Playgroud)