《深入理解计算机系统》 练习题2.36答案
强制类型转换与其他运算的先后
int main(void)
{
int x = -pow(2, sizeof(int) * 8 - 1); /* Tmin */
int y = -1;
auto z1 = (int64_t)x * y;
auto z2 = x * (int64_t)y;
auto z3 = (int64_t)x * (int64_t)y;
auto z4 = (int64_t)(x * y);
}
注意z1变量,是先进行类型转换,然后再执行乘法,再会隐式地将y进行类型转换,再继续执行乘法。
z2,z3变量都是一回事。
注意z4变量,(x * y)
这里还是int型的,所以这里正溢出,进行截断,还是-2147483648。然后进行类型转换,即进行位拓展,新拓展的位上的值都为1。
代码
此函数为初始版本,是用除法来检测的:
int tmult_ok(int32_t x, int32_t y)
{
int32_t p = x * y;
/* Either x is zero, or dividing p by x gives y */
return !x || p / x == y;
}
先提前扩大两个数的范围,再执行乘法。
然后再进行截断,因为截断之后就相当于把乘积mod ,取余的范围为【0,-1】。如果截断以后,值不相等,那么就出现溢出了。
int tmult_ok2(int32_t x, int32_t y)
{
int64_t p = (int64_t)x * y; /*一定要先将右边手动转成 int64_t */
/*printf("p=%" PRId64 ", q=%" PRId32 "\n", p,q);*/
return p == (int32_t)p;
}
参考链接:
[1] https://github.com/vonzhou/CSAPP/blob/master/exercise/ex2-36.c
[2] https://github.com/haiiiiiyun/book_exercises/blob/master/csapp-v3/chap2/2.36.c