使用无符号索引在 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_t
(s
的类型)。 -1
不能用无符号类型表示,因此我们应用模运算将其置于范围内。这给了我们 SIZE_MAX
(类型 size_t
的最大可能值)。类似地,当 0
时递减 s
以 SIZE_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 在迭代中使用足够大的有符号值。它更容易被人类阅读。
以下代码可以安全地向后迭代数组吗?
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_t
(s
的类型)。 -1
不能用无符号类型表示,因此我们应用模运算将其置于范围内。这给了我们 SIZE_MAX
(类型 size_t
的最大可能值)。类似地,当 0
时递减 s
以 SIZE_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 在迭代中使用足够大的有符号值。它更容易被人类阅读。