CSAPP Notes: Types

发布时间 2023-08-22 22:31:53作者: K1øN

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]
}

iunsigned 类型的时候,会 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. 取反再+1;
  2. 第一位理解成负数,比如 -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 :他是没有对应的正数的;

大端与小端

内存按照递增顺序排列——

大端就是好认的那种;

浮点数

不想学()