小蒙 发表于 2017-10-7 10:52:36

两个int的乘积会在返回之前被截断成int???

本帖最后由 小蒙 于 2017-10-7 11:00 编辑

题目来自C primer plus 6th第六章复习题的13题。

答案如下:
long x(int i)
{
    return i * (long)i;
}

之所以要把形参强制转换成long,答案解析中是这么说的。
把i的类型强制转换成long,确保计算使用long而不是int,在int位16位的系统中,两个int类型值得乘积在返回之前会被截断成int,这可能丢失数据。

经过验证,确实如此。
int i = 2147483647;//i赋予最大值
long l = (long)i * i;
printf("%ld\n", l);
如果不加long强制转换,结果输出1,加了转换,结果正确,为4611686014132420609

丶忘却的年少o 发表于 2017-10-7 10:54:25

嗯?你想问的是什么?{:10_245:}

小蒙 发表于 2017-10-7 11:00:27

丶忘却的年少o 发表于 2017-10-7 10:54
嗯?你想问的是什么?

正在编辑中。。。

丶忘却的年少o 发表于 2017-10-7 11:04:25

小蒙 发表于 2017-10-7 11:00
正在编辑中。。。

对呀,答案说的没错呀,就是怕i的数太大,导致int类型存不下,所以要把它转换为一个能存放大的类型,就能存放,不会导致数据的丢失呀。
至于转换就是像程序里的一样return i * (long)i;也可以return (long)i * i;

ba21 发表于 2017-10-7 11:06:21

这跟float 和 double 同理。float不强转double再计算 数值会越界。

意思是把计算后的结果给 long l 。至于你的结果是什么l 是不管的。结果取决于 i * i 里面能容纳的最大数据类型

小蒙 发表于 2017-10-7 11:10:32

丶忘却的年少o 发表于 2017-10-7 11:04
对呀,答案说的没错呀,就是怕i的数太大,导致int类型存不下,所以要把它转换为一个能存放大的类型,就能 ...

int i = 2147483647;
long l =i * i;
printf("%ld\n", l);
两个i相乘,如果按照i的取值范围看,乘积确实超出了int的取值范围,可是我定义的是long类型,long类型是可以存放下这个大小的乘积的,感觉你说的确实是计算机内部的真实情况,但是我想不到理论根据。

我是师兄 发表于 2017-10-7 11:17:12

int * int 的结果是 int
所以溢出
int * long 结果是 long
所以没溢出

i*i 的类型 只和两个操作数的类型有关系
和你的函数返回值类型没关系
你返回值类型是long
只是把计算结果 转换成 long 而已
相当于return (long)(i*i);
i*i 溢出到了 1
相当于
return (long)1;
还是 1

小蒙 发表于 2017-10-7 11:20:30

我是师兄 发表于 2017-10-7 11:17
int * int 的结果是 int
所以溢出
int * long 结果是 long


感谢!

小蒙 发表于 2017-10-7 11:22:13

丶忘却的年少o 发表于 2017-10-7 11:04
对呀,答案说的没错呀,就是怕i的数太大,导致int类型存不下,所以要把它转换为一个能存放大的类型,就能 ...

感谢前辈,对于初学者的我,7楼的解答我听得更明白{:10_250:}

小蒙 发表于 2017-10-7 11:22:52

ba21 发表于 2017-10-7 11:06
这跟float 和 double 同理。float不强转double再计算 数值会越界。

意思是把计算后的结果给 long l 。至 ...

感谢版主,7楼的解答,作为初学者,我听得更明白{:10_250:}
页: [1]
查看完整版本: 两个int的乘积会在返回之前被截断成int???