使用无符号索引在 C 中向后迭代数组

Iterating an array backward in C using an unsigned index

以下代码可以安全地向后迭代数组吗?

for (size_t s = array_size - 1; s != -1;  s--)
    array[s] = <do something>;

请注意,我正在比较 s,即 unsigned-1

有没有更好的方法?

嗯,s 永远不会是 -1,所以你的结束条件永远不会发生。 s 将从 0 变为 SIZE_MAX,此时您的程序可能会因内存访问错误而出现段错误。更好的解决方案是从最大尺寸开始,然后从您使用它的所有地方减去一个:

for (size_t s = array_size; s > 0; s--)
    array[s-1] = <do something>;

或者您可以将此功能组合到 for 循环的语法中:

for (size_t s = array_size; s--;)
    array[s] = <do something>;

这将在进入循环之前减去 1,但在减去 1 之前检查 s == 0

这段代码非常棘手。如果我对 C 标准的理解是正确的,那么如果 size_t 至少与 int 一样大,那么您的代码就是安全的。通常是这种情况,因为 size_t 通常实现为 unsigned long int.

在这种情况下,-1 被转换为 size_ts 的类型)。 -1 不能用无符号类型表示,因此我们应用模运算将其置于范围内。这给了我们 SIZE_MAX(类型 size_t 的最大可能值)。类似地,当 0 时递减 sSIZE_MAX+1 为模完成,这也会导致 SIZE_MAX。因此,在处理 s = 0 案例后,您的循环恰好在您希望它结束​​的地方结束。

另一方面,如果 size_t 类似于 unsigned short(并且 int 大于 short),那么 int 可以表示所有可能的size_t 值和 s 将转换为 int。换句话说,比较将按 (int)SIZE_MAX != -1 进行,这将始终 return false,从而破坏您的代码。但我从未见过会发生这种情况的系统。


您可以使用 SIZE_MAX(由 <stdint.h> 提供)代替 -1:

来避免任何潜在的问题
for (size_t s = array_size - 1; s != SIZE_MAX;  s--)
    ...

但我最喜欢的解决方案是:

for (size_t s = array_size; s--; )
    ...

IMO 在迭代中使用足够大的有符号值。它更容易被人类阅读。