CSAPP

2147483647(231-1)
4294967295(232-1)

问题:
1)位运算中<<要是位移负数位捏,比如1<<-2
2)无符号数没有原码,反码,补码一说吗?
3)

1.给C语言初学者:C C++ java中的有符号数和无符号数
C和C++都支持有符号(默认)和无符号数。Java只支持有符号数

通常数字大多数数字都默认为是有符号的,比如在编译器中声明一个像
12345或者0x1A2B这样的常量的时候,这个值就被认为是有符号的。

注意:
在64位机器上1分配Int类型(4字节),似乎32位的机器上也是。
1.在计算机中,凡是≤2147483647(231-1)的常量声明,在计算机中默认是4个字节,即32位表示的有符号的int的编码
C语言里面的常量默认是一个32位的有符号整型数
2.如果想要将long long 类型的数字常量赋值,那么需要在这个数的后面
即:如果赋>2147483647(231-1)的数,需要在初值后面加上LL,否则会编译错误
此外,如果用移位的方式赋值给long long要记得把默认用4字节有符号整数表示的1变成8字节有符号整数。
测试(1):
//下面这一行把默认用4字节有符号整数表示的1变成8字节有符号整数。
long long a = ((long long)1 << 32);
cout << a;
输出:4294967296 输出正常
测试(2):
long long a = 123456789012345LL;
cout << a;
输出正常。//但是我把LL删掉,在VS2017和devC++中都也可以。

测试1:
int a=2147483647;
cout<<a<<endl;
输出正常
测试2:
int a=2147483648;
cout<<a<<endl;
输出却是:-2147483648,解释:
2147483648=2147483647+1
因为+2147483648在32位有符号数中应该编码为:
01111111 11111111 11111111 11111111

  • 00000000 00000000 00000000 00000001
    ————————————————————
    10000000 00000000 00000000 00000000
    所以输出是这样的。
    测试3:

2.有符号数和无符号数之间的转换
这种强制类型转换其实,它的结果保持位值不变,只是改变了解释这些位的方式。
测试:
unsigned int a=1<<31;
int b=1<<31;
cout<<a<<endl;
cout<<b<<endl;
输出:
2147483648
-2147483648

测试:
int b=1<<31;
unsigned int a=(unsigned)b;
cout<<b<<endl;
cout<<a<<endl;
输出:
-2147483648
2147483648

测试:
unsigned int b=1<<31;
int a=(int)b;
cout<<b<<endl;
cout<<a<<endl;
输出:
2147483648
-2147483648

3.扩展一个数字的位表示

<1>从有符号整数转换到一个更大的有符号的数据类型
测试(1):
int b = -2147483647;
long long a = b;
cout << a;
输出为:-2147483647
<2>从无符号整数转换到一个更大的无符号的数据类型
测试(2):
unsigned int b = 4294967295;// 4294967295(232-1)
unsigned long long a = b;
cout << a;
输出为:4294967295

4.截断数字
假设我们不用额外的位来扩展一个数值,而是减少表示一个数字的位数。

1.无符号大的-》无符号小的
测试(1)
unsigned long long b = 4294967296; // 4294967295+1(232-1+1)
unsigned int a=b;
cout << a;
输出为:0
解释,unsigned long long 类型中
// 4294967295+1(232-1+1)
二进制表示为
00000000 00000000 00000000 00000001 00000000 00000000 00000000 00000000
而转换为unsigned int
二进制表示为
其实就是丢弃最高的32位,留下后面的00000000 00000000 00000000 00000000
意思就是0
测试(2)
unsigned long long b = 4294967297;
unsigned int a=b;
cout << a;
输出:1
解释同上。

2.有符号大的-》有符号小的
long long b = -2147483648LL;
int a=b;
cout << a;
输出:-2147483648
注意:在这里,必须在后面加上LL
不然在devC++中显示
[Warning] this decimal constant is unsigned only in ISO C90 [enabled by default]
而在VS2017中则直接不让通过,所以在给long long赋负数的时候,还是最好加上LL