Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无符号倒计时的正确方法_C_Loops_Unsigned - Fatal编程技术网

C 无符号倒计时的正确方法

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

我正在读卡内基梅隆大学计算机系统的幻灯片,准备参加我的测验。在第49页:

无符号倒计时
使用无符号作为循环索引的正确方法

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