CSAPP Notes,类型
随手写的,可能会有错误();
类型
数据类型 | 大小 |
---|---|
char |
1 |
bool |
1 |
short int (short) |
2 |
int |
4 |
long int (long) |
4 或 8 (取决于平台) |
long long int |
8 |
float |
4 |
double |
8 |
long double |
8 或 16 (取决于平台) |
wchar_t |
2 或 4 (取决于平台) |
size_t |
4 或 8 (取决于平台) |
ptrdiff_t |
4 或 8 (取决于平台) |
不取决于平台的类型:
数据类型 | 大小 |
---|---|
std::int8_t |
1 |
std::int16_t |
2 |
std::int32_t |
4 |
std::int64_t |
8 |
std::uint8_t |
1 |
std::uint16_t |
2 |
std::uint32_t |
4 |
std::uint64_t |
8 |
要注意一些情况可能在不经意间导致 wrap around, 然后导致死循环——尤其是在处理 unsigned
类型的时候.
unsigned int i;
for (i = __; i < cnt; i--) {
a[i] = a[i + 1]
}
或者更加难以察觉的:
size_t i;
for (i = __; i < cnt; i--) {
a[i] = a[i + 1]
}
在 i
是 unsigned
类型的时候,会 wrap around 导致死循环——这是一类难以察觉的错误;
所以要确保 for
循环里的变量是有符号的;
补码
补码的理解
十进制 | 二进制(原码) | 补码 |
---|---|---|
0 | 00000000 | 00000000 |
1 | 00000001 | 00000001 |
-1 | 10000001 | 11111111 |
2 | 00000010 | 00000010 |
-2 | 10000010 | 11111110 |
3 | 00000011 | 00000011 |
-3 | 10000011 | 11111101 |
第一位是符号位;剩下的是数字位.
补码的几种理解:
- 取反再+1;
- 第一位理解成负数,比如 -2 是 \(-2(dec) = 01111110(bin) + (-10000000)(bin)\);
补码的性质
加法和乘法运算封闭——所以物理上,底层的运算逻辑可以复用无符号的那一套东西;
右移
算数右移和逻辑右移是有区别的;
逻辑右移
逻辑右移就是照字面进行右移;
例如,考虑一个8位的二进制数:10111010
,进行逻辑右移1位:
Copy code
原始数值: 10111010
逻辑右移: 01011101
在这个例子中,原始数值向右移动一位,右侧的位被丢弃,同时在左侧插入一个零位。
算数右移
例如,考虑一个8位的二进制数:10111010
,进行算数右移1位:
Copy code
原始数值: 10111010
算数右移: 11011101
在这个例子中,原始数值向右移动一位,同时在左侧插入一个与原始符号位相同的位值。
在 C/C++ 中只有算数右移,在 Java 中两种都有显示的定义;
所以在 C/C++ 中,右移运算 >>
只对有符号的类型有意义;对于无符号的类型是无意义的;
例
unsigned int ux = -100;
if (ux > -1) {
cout << "true" << endl;
}
else {
cout << "false" << endl;
}
输出:
false
unsigned int ux = 100;
if (ux > -1) {
cout << "true" << endl;
}
else {
cout << "false" << endl;
}
输出:
false
例:负数的负数
int x = INT_MIN;
cout << x << endl;
cout << -x << endl;
输出:
-2147483648
-2147483648
所以负数的负数不一定是正数.
这是由于补码的不对称性导致的,事实上也就只有这一种情况,就是最小的那个数 INT_MIN
:他是没有对应的正数的;
大端与小端
内存按照递增顺序排列——
大端就是好认的那种;
浮点数
不想学()
标签:右移,std,CSAPP,int,Notes,补码,unsigned,long,Types From: https://www.cnblogs.com/kion/p/17649861.html