疑问:书中称该程序会无限循环,但编译器仅有限运行?请判断该while循环是否无限执行
这个while循环会无限执行吗?
先看你给出的代码:
#include <stdio.h> int main() { int i; i = 1; while (i <= 32767) { printf("%d", i); i = i + 1; } }
为什么书籍说它会无限循环?
这个说法是基于16位有符号整数的场景:在早期的16位系统中,int的取值范围是 -32768 到 32767。当i递增到32767时,执行i = i + 1会触发有符号整数溢出。在补码(几乎所有现代系统都采用的整数表示法)中,32767(二进制01111111 11111111)加1后会变成10000000 00000000,也就是-32768。这时候i <= 32767的条件依然成立(毕竟-32768肯定小于32767),循环会继续:i从-32768开始再次递增到32767,然后又溢出到-32768,如此往复,理论上就会进入无限循环。
为什么实际编译器只让它运行有限次数?
现在你看到的结果和书籍描述不符,主要有两个核心原因:
int的位数已经变大了:现代编译器默认的int通常是32位(甚至64位),32位有符号整数的范围是-2147483648到2147483647,这个上限远高于32767。所以当i到32767再加1时,会得到32768,这时候32768 <= 32767不成立,循环直接终止,总共运行32767次。- 编译器对未定义行为的优化:即使你在16位环境下编译,有些编译器可能会利用“有符号整数溢出是未定义行为”这一点做优化。比如编译器会假设
i是严格递增的,既然初始值是1,那么最终i一定会超过32767,所以会把循环优化成有限次数的执行。不过这种优化是编译器自主决定的,不是所有情况都会发生。
关键知识点:有符号整数溢出是未定义行为
C标准明确规定,有符号整数溢出属于未定义行为——这意味着编译器可以任意处理这种情况:让程序崩溃、终止循环、或者真的进入无限循环,都是符合标准的。所以书籍的说法是补码实现下的常见场景,但实际运行结果会因编译器、系统架构的不同而变化。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

