C-为什么在使用uint64_t计数器时for循环会卡住,而while循环是';T
当我使用带有C-为什么在使用uint64_t计数器时for循环会卡住,而while循环是';T,c,for-loop,while-loop,uint64,C,For Loop,While Loop,Uint64,当我使用带有uint64\u t的for循环作为计数器时,它会永远卡住,即使条件似乎定义得很好 冒犯性的MCVE #include <stdio.h> #include <inttypes.h> int main() { uint64_t i; for (i = 15; i >= 0; i--) { printf("%"PRIu64" ", i); } return 0; } #include <stdio.h> #inclu
uint64\u t
的for
循环作为计数器时,它会永远卡住,即使条件似乎定义得很好
冒犯性的MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i;
for (i = 15; i >= 0; i--) { printf("%"PRIu64" ", i); }
return 0;
}
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i = 16;
while (i--) { printf("%"PRIu64" ", i); }
return 0;
}
它似乎忽略了停止条件,所以它翻滚了
但是,将其更改为“等效”while循环时,一切正常:
正确的MCVE
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i;
for (i = 15; i >= 0; i--) { printf("%"PRIu64" ", i); }
return 0;
}
#include <stdio.h>
#include <inttypes.h>
int main() {
uint64_t i = 16;
while (i--) { printf("%"PRIu64" ", i); }
return 0;
}
在
for
循环中使用uint64\u t
计数器时,我是否遗漏了一些内容?非常感谢您的帮助 如果i
是无符号类型,则条件i>=0
通常为真。递减无符号零不会产生负值,但计数器将换行到给定类型的最大可表示数
C表示包含下限和排除上限的范围。例如,N
元素数组的索引为0到N-1
。上限本身不是有效的数组索引
此约定意味着您在递增某个值之前使用该值,但在使用该值之前先取消该值。考虑一个简单的堆栈:
stack[nstack++] = x; // push a value
x = stack[--nstack]; // pop a value
同样的逻辑也适用于循环:向前移动时,在递增之前使用该值:
for (var i = 0; i < N; i++) { use(i); }
此循环相当于您的while
。在处理主体之后发生的更新部分在这里是空的。在进入循环之前对值进行检查;循环体具有更新的值
对于空的更新部分,这种向后循环可能看起来很尴尬,但在其他方面,它与向前版本正交:
- 它使用实际边界;没有必要从
N-1开始李>
- 它同样适用于任意边界,只要它们遵循包容下界和排斥上界的约定李>
- 测试是一个纯粹的不等式,而不是一个大于/小于或等于的比较
i
为无符号整数类型,则表达式i>=0
始终为真。另一种简单的方法是将其更改为:
uint64_t i;
for (i = 15; i != -1; i--) { ... }
i != (uint64_t)-1
无论i
是有符号整数还是无符号整数,这都有效。在uint64\u t
情况下,-1将首先转换为0xffffffffffff
,然后与i
进行比较
如果要消除编译警告,请将其更改为:
uint64_t i;
for (i = 15; i != -1; i--) { ... }
i != (uint64_t)-1
但是您需要确保
uint64\t
的类型恰好是i
i>=0
对于未签名的对象始终为真。i=0后,它将环绕到最大值,而不是-1,因此如果使用GCC,停止表达式不会为假,始终使用-Wall-Wextra
进行编译,以获取有关此类问题的有用警告。如果使用MSVC编译,请使用-Wall
.i>=0始终为true,您可以将其更改为i!=-等效的,而循环将是uint64\t i;i=15;而(i>=0){printf(“%”PRIu64“,i);i--;}
。这也会显示一个无限循环,就像您的for
循环一样。另请参见@logo\u writer,您可以随时更改要接受的答案。只需等待一天,选择最佳答案。其他读者稍后可能会提供更好的答案。