Site Overlay

CSAPP 复习笔记:整型数据类型

知识点

参考:

例题

【例子】 求 0xF 的无符号和补码表示

0xF = 1111,无符号 sum(8,4,2,1) = 15,补码:-8 4 2 1 = -1

【例子】 求补码 -8, -3 转无符号表示

-8: 1000 = 8
-3 = -8 + 5 = 1101 = 8 + 4 + 1 = 13

【例子】 求有符号数 -2 转无符号数。

-2: (0...10)'+1 = (1...10)
其加一等于 UINT_MAX,所以它是 UINT_MAX - 1

【例子】 int32, -2147483647-1 会发生什么?

会得到补码的最小值 10...0

【例子】 int32, -2147483648-1 会发生什么?

 10...0
+11...1
=01...1

也就是得到了 INT_MAX = 2147483647
(其实还会在编译时得到一个警告)

【知识点】 有符号数和无符号数比较、计算时,会统一转换为?

无符号数 (...U)(提醒一点,如果无符号数经过 int 强转,比如 (int)0xabcU 的形式,那么应该当做有符号数)

比如,比较 UINT_MAX - 1 和 INT_MIN - 1,右边会转换为无符号表示,相当于 INT_MAX

【知识点】 算数右移和逻辑右移的区别?

算数右移:移动之后的空位根据移动之前的符号填充。 比如 0001 >> 1 = 1000 (用 1 填充了左边的空位)

逻辑右移:直接移动,空位填 0。比如 0001 >> 1 = 0000.

【知识点】 有符号数值的右移是[],而无符号数值的右移是[]

有符号数值的右移是算术右移,而无符号数值的右移是逻辑右移

【例子】 判断对错:ux>-1

错,-1 被转换为无符号,变得很大。

【例子】 判断对错:ux>>3==ux/8

正确,无符号是逻辑右移。

【例子】 -1>>1 是多少?

有符号是算数右移,会在左边符号位补 1,因此结果还是 -1

【例子】 判断对错:x>>3==x/8

错。负数右移不是除法!负数右移不是除法!负数右移不是除法!

不妨观察下面的程序:

int main()
{
    int n = -9;
    printf("%x\n", n);
    printf("%x\n", n>>1);
    printf("%x\n", n>>2);
    printf("%x\n", n>>3);
    printf("%x\n", n>>4);
    printf("%x\n", n>>5);
    return 0;
}

结果是

fffffff7
fffffffb
fffffffd
fffffffe
ffffffff
ffffffff

只看最低位,变化是:0111->1011->1101->1110->1111,可以发现负数右移是在向 -1 靠近,并不是做除法。

【例子】 如何判断两个整数相加是否会溢出?

int s = x + y;
if ((x>0 && y>0 && s<=0) || (x<0 && y<0 && s>=0)){
    // 溢出
}

【例子】 如何求一个数的加法逆元?

取反加一(不分正负)

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注