知识点
参考:
例题
【例子】 求 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 会发生什么?
+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
错。负数右移不是除法!负数右移不是除法!负数右移不是除法!
不妨观察下面的程序:
```c
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;
}
结果是
fffffffb
fffffffd
fffffffe
ffffffff
ffffffff```
只看最低位,变化是:0111->1011->1101->1110->1111,可以发现负数右移是在向 -1 靠近,并不是做除法。
【例子】 如何判断两个整数相加是否会溢出?
```c
int s = x + y;
if ((x>0 && y>0 && s<=0) || (x<0 && y<0 && s>=0)){
// 溢出
}
【例子】 如何求一个数的加法逆元?
取反加一(不分正负)