#define A_SIZE 11
int array[A_SIZE];
...
for (size_t i = A_SIZE; i-- > 0; ) {
// Do something, f.ex. array[i] = i
}
OTOH,代码可能在循环中具有break条件,并且在后面的代码中需要i来指示array[]的使用
size_t i = A_SIZE;
while (i > 0) {
if (...) break;
i--;
// Do something, f.ex. array[i] = i
if (...) break;
}
// Do something with i
代码可能有一个 * 合同要求 * 在不同的地方使用10。
// Contract says loop must handle indexes 0 to N, inclusive
#define N 10
int array[N + 1];
for (size_t i = N; i + 1 > 0; i--) {
// Do something, f.ex. array[i] = i
}
6条答案
按热度按时间cedebl8k1#
当溢出发生时,它将舍入到最大整数,因此条件将失败。
c3frrgcw2#
从技术上讲,它不是溢出,因为
size_t
是无符号类型,但它肯定是一个无限循环,因为终止条件始终为真。无符号整数在
0
处递减时 * 环绕 *。请注意,循环将在回绕发生之前运行11
次,而不是10
次。在递减索引之前必须检查条件。以比最大有效索引大一的初始值开始枚举,可以提高视觉一致性并简化测试。
下面是一个修正后的版本,你可以看到
i
的初始值是数组的元素数:az31mfrm3#
注意:问题以value=10开始循环(这很奇怪,但并非不可能)。我从11开始,但第一次进入循环体时,它已经递减到10了。
f2uvfpb94#
惯用的方法是使用slide操作符,虽然不是每个人都喜欢:
它不是一个真正的运营商,但这就是它多年来所知道的。
0x6upsns5#
size_t i = 10; i >= 0;
永远不会为false,因为size_t
是某种无符号类型,并且所有值都大于或等于零。...
size_t
,它是sizeof
运算符结果的无符号整数类型;...C11 §7.19 2
开启所有警告
一个好的编译器如果启用了警告功能,就会对此发出警告。
希望那个死循环永远不会发生,因为对警告的调查会首先纠正这个问题。
最佳选择取决于编码目标
好的代码避免了像裸10这样的神奇数字。最好是代码派生出来的。在这个简单的例子中,它应该是11。
OTOH,代码可能在循环中具有
break
条件,并且在后面的代码中需要i
来指示array[]
的使用代码可能有一个 * 合同要求 * 在不同的地方使用
10
。好的优化编译器不会在每个
i + 1 > 0
上执行+1
,而是创建等效的高效代码。代码是一种最能传达代码整体含义的时尚。
muk1a3rh6#
最简单的方法是增加上限值。举个例子
或
在一般情况下,当i可以等于存储在
size_t
类型的对象中的最大值时,可以使用以下技巧否则,可以使用do-while循环。在这种情况下更合适。举个例子