为何输入负数时while循环未死循环且最终输出0?
问题分析:输入-1时阶乘代码的行为解释
首先看你的阶乘代码:
#include <stdio.h> int main(void) { unsigned long long f; int n; printf("factorial:"); scanf("%d", &n); printf("%d! = ",n); f = n; while (--n) f*=n; printf("%llu\n",f); return 0; }
1. 为什么没有陷入死循环?
你以为输入负数时while(--n)会一直循环,是默认n会一直保持负数,但实际上n是有符号int类型,它的取值范围是有限的(比如32位int是-2147483648到2147483647,16位int是-32768到32767)。
当输入n=-1后,每次执行--n:
- 一开始n从-1不断减小,直到达到int的最小值(比如
-2147483648); - 此时再执行
--n,会触发有符号整数溢出(大多数编译器按补码规则处理,最小值减1会绕回最大值); - 之后n从最大值开始不断减小,直到n=1时,执行
--n得到0,while(0)条件不成立,循环终止。
所以循环最终会结束,只是循环次数等于int类型的取值总数(32位是231次,16位是216次),现代计算机能快速完成这个循环。
2. 为什么最终输出0?
f是unsigned long long(64位无符号整数),它的取值范围是0到18446744073709551615。
循环过程中f会不断乘以转换为unsigned long long的n:
- 初始时
f = -1,但因为f是无符号类型,-1会被转换为unsigned long long的最大值18446744073709551615; - 循环中会多次乘以偶数(比如-2、-4、2、4等),每次乘偶数都会给乘积增加2的因子;
- 当乘积中积累了至少64个2的因子时,
f的值就会变成0(64位无符号数无法存储264,溢出后模264结果为0); - 一旦
f变成0,后续再乘以任何数结果还是0,直到循环结束,最终输出0。
内容的提问来源于stack exchange,提问作者DayofCoding
相关产品推荐
相关产品推荐

