老婆最近在网上学 C 语言。晚上她跟我说有一章的习题她看不懂,让我帮忙看看。题目在这儿(http://c.biancheng.net/cpp/html/58.html)。

看了许久觉得不对劲,感觉代码有问题,可它的代码实际运行的结果确是和题目答案一致的。最后终于发现题目的代码连同答案本身都是错的。很多人都发现习题的答案是错的并留了评论,可是有没有想过题中错误的结果是如何得出的呢?

题中代码运算逻辑等价于 factorial(10) _ 10,即 10^10 _ 10,又即 100000000000(1 后面跟 11 个 0)。可为什么程序跑出来的结果却是 1215752192 呢?

我们先来看 factorial 函数。由代码逻辑可得 factorial(10)= 10^10。可实际运行结果如下:

当i=1:
result=10
当i=2:
result=100
当i=3:
result=1000
…
当i=8:
result=100000000
当i=9:
result=1000000000
当i=10:
result=1410065408

为什么 i=10 时,result=1410065408 呢? 因为 10^10 超出了 long 数据类型(占 4 字节内存空间)所能表达数字的范围,溢出了。

overflow

为了证实这一猜测,我们可以用程序员计算器查看 10^10 的二进制表示,即:10 0101 0100 0000 1011 1110 0100 0000 1000。取其后 32 位,即 0101 0100 0000 1011 1110 0100 0000 1000,以十进制表示可得 1410065408。由此证明,1410065408 是 10^10 以 long 数据类型表示的结果。同样可以证明,题中代码运行结果 1215752192 也是 10^11 以 long 数据类型表示溢出后的结果。

proof