CSAPP学习之关于两个整数相乘的思考
相信大家都知道两个数的平方在数学上一定是大于0的,但是在C语言中就不一定了。
代码如下:
#include <stdio.h>
#include <stdlib.h>
int sq(int x) {
return x*x;
}
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
int x = atoi(argv[i]);
int sx = sq(x);
printf("sq(%d) = %d\n", x, sx);
}
return 0;
}
在Linux上运行结果为:
hxl@hxl-virtual-machine:~/桌面/task/code$ gcc -o s sq.c
hxl@hxl-virtual-machine:~/桌面/task/code$ ./s 50000
sq(50000) = -1794967296
先解释这段代码,
1.int argc 表示的是参数的个数,如果没有参数则为1,即实际的参数个数+1为argc的大小。
2.char *argv[]是一个参数数组,里面的元素是char型的,argv[1]表示的是第一个实际参数,后面的参数,依此类推。
3.函数atoi()是C语言标准库函数里的,功能是将一个char型的变量转换为int型。
再看原因:
我们知道int型变量是4个字节的,即32位,所能表示的最大值是用二进制表示为第一位为0,后面31个1,大小为2的31次方-1,等于2147483647,从范围来看50000*50000=2500000000超过了范围,所以显示了不正确的值。
鉴于32位位数太多,不方便进行算数演示,则取5位来演算,首先范围为-16到15。我们取5和5相乘,本应该得25的,但是超出了范围,那怎么去知道计算机得出的是个什么数呢?5的5位二进制表示为00101,则两者相乘得011001,因为只有5位,则表示为11001,得到结果为-7。还有就是先将25的二进制写出来(用尽量少的位数表示)011001,还是取后5位,得11001,还是-7。
这就解释了为什么两个int型整数相乘可能得到一个负数了。