C 无符号倒计时的正确方法
我正在读卡内基梅隆大学计算机系统的幻灯片,准备参加我的测验。在第49页: 无符号倒计时C 无符号倒计时的正确方法,c,loops,unsigned,C,Loops,Unsigned,我正在读卡内基梅隆大学计算机系统的幻灯片,准备参加我的测验。在第49页: 无符号倒计时 使用无符号作为循环索引的正确方法 unsigned i; for (i = cnt-2; i < cnt; i--) a[i] += a[i+1]; 无符号i; 对于(i=cnt-2;i=0的循环条件不起作用。无符号数字总是大于或等于0,因此这样的条件将为空。i
使用无符号作为循环索引的正确方法
unsigned i;
for (i = cnt-2; i < cnt; i--)
a[i] += a[i+1];
无符号i;
对于(i=cnt-2;i
更好
size_t i;
for (i = cnt-2; i < cnt; i--)
a[i] += a[i+1];
size\u ti;
对于(i=cnt-2;i
我不明白为什么它不是无限循环。我正在递减
I
,它是无符号的,因此它应该始终小于cnt
。请解释。循环的目标是从cnt-2
向下循环到0
。它实现了写入i>=0
的效果
上一张幻灯片正确地讨论了为什么i>=0
的循环条件不起作用。无符号数字总是大于或等于0
,因此这样的条件将为空。i
的循环条件结束循环,直到i
通过0
并环绕。当您减少无符号0
时,它将变为UINT\u MAX
(对于32位整数为232-1)。当这种情况发生时,i
保证为false,循环终止
我不会这样写循环。这在技术上是正确的,但风格很差。好的代码不仅仅是正确的,它是可读的,因此其他人可以很容易地知道它在做什么。这个循环仅仅依赖于一个事实,即
i
将递减超过0,这使它成为最大uint值。这打破了循环,因为现在i
Per:
无符号数字不能溢出,而是使用
模的性质
< C和C++标准都保证了这种UnTin包装行为,但是对于有符号整数是不确定的。 < P>这是一个可替代的表达式,用于实现相同的事物所建立的成语。
for (unsigned i = N; i != -1; --i)
...;
它们只是简单地替换了i!=-1
带有略为神秘的i
。当0
在unsigned
域中递减时,它实际上环绕到UINT_MAX
值,该值比较等于-1
(在unsigned域中),并且大于或等于cnt
。所以,要么i!=-1
或i
作为继续迭代的条件
为什么他们会这样做呢?显然是因为它们从cnt-2
开始,并且cnt
的值可以小于2
,在这种情况下,它们的条件确实工作正常(并且i!=-1
不正常)。除此之外,没有理由将cnt
纳入终止条件。有人可能会说,更好的办法是预先检查cnt
的值,然后使用i!=-1
习语
if (cnt >= 2)
for (unsigned i = cnt - 2; i != -1; --i)
...;
注意,顺便说一句,只要已知
i
的起始值为非负,则基于i!=-1
条件有效,无论i
是有符号还是无符号。它利用了将无符号整数0减量时发生的情况。这里有一个简单的例子
unsigned cnt = 2;
for (int i = 0; i < 5; i++) {
printf("%u\n", cnt);
cnt--;
}
无符号整数0-1变为UINT\u MAX
。因此,不要寻找-1,而是观察计数器何时变得大于其初始状态
将示例稍微简化一点,下面是如何从5(独占)倒计时到0
在最后一次迭代中,i=UINT_MAX
保证大于cnt
,因此i
为假
size\u t
是“更好的”,因为它是无符号的,并且与C中最大的东西一样大,所以您不必确保cnt
与i
是同一类型,我想您会混淆int和无符号int数据类型。这两个是不同的。在int数据类型(2字节存储大小)中,其范围为-32768到32767,而在无符号int数据类型中(2字节存储大小)。您的范围从0到65535。
在上面提到的例子中,您正在使用类型为unsigned int的变量i。它将递减到i=0,然后根据语义结束for循环。它确实具有为
cnt
=0工作的优点。虽然对于这个问题有很多正确的候选解决方案,但您的答案更详细。谢谢我认为这是不受支持的,错误:常量-1与类型为'uint8_t'(也称为'unsigned char')的表达式的比较总是正确的
无符号I=cnt-1有任何错误;而(i--)a[i]=a[i+1]?@ DaviC.RANKIN Robert Seacord推荐后者,因为长度将大约是单词的大小。它的重复可能产生与<代码>无符号I=CNT - 1相同的迭代;而(i--)printf(“%u\n”,i)但使用后减量运算符,该运算符允许在循环体内计算i=0
,然后在条件下终止,而在下一次检查(后减量之前)时(0)
。
2
1
0
4294967295
4294967294
unsigned i;
unsigned cnt = 5;
for (i = cnt-1; i < cnt; i--) {
printf("%d\n", i);
}
4
3
2
1
0