CSAPP 学习随笔(2):Bits-ints-part1

Word Size 字长

  • 32位(bits)机器,字长为4Bytes(32/8),寻址空间为$2^{32} = 4 * 2^{30} = 4GB$;
  • 内存中的管理方式如下,32位的机器最小连续字间隔4Byte,64位的机器最小连续字间隔8Byte,字节Byte是最基本存储单元;

数据表示

  • int可以跨平台兼容,long和pointer一样:

数据的存储排列


解答:0x08000100;

字的存放问题

  • 大端法(高对低,最低有效字节在高低址);
  • 小端法(低对低,最低有效字节在最前(低地址))
  • int x = 0x01234567, &x = 0x100为例:
Address 0x100 0x101 0x102 0x103
Big Endian 01 23 45 67
Little Endian 67 45 23 01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

typedef unsigned char *pointer;

void show_bytes(pointer start, size_t len){ // 从数据的指针开始打印数据,即从低地址开始打印
size_t i;
for (i = 0; i < len; i++)
printf("%p\t0x%.2x\n",start+i, start[i]);
printf("\n");
}

int main(void) {
int a = 15213; // 15213 = 00 00 3b 6d;
printf("int a = 15213;\n");
show_bytes((pointer) &a, sizeof(int));

int b = -15213;
printf("int b = -15213;\n");
show_bytes((pointer) &b, sizeof(int));

char s[6] = "18213";
printf("string s = \"18213\"\n");
show_bytes((pointer) &s, sizeof(s));
return 0;
}
  • 注意对于字符数组,存储时每个字符按照小端法存储,所以表现出来的结果是整个字符串小端法和大端法没有区别;

字的边界对齐问题

  • 按边界对齐:(以32位机器为例,按字节编址,4个字节同时读写)
    • 字地址:4的倍数;
    • 半字地址:2的倍数;
    • 字节地址:任意;
  • 浪费了一些空间,但减少了访存次数;

运算

布尔运算

  • 按位与,按位取反;
  • $\sim 0x41(01000001) \rightarrow 10111110 = 0xBE$;
  • $\sim 0x00\rightarrow 0xFF$;
  • $0x69 & 0x55 \rightarrow 01101001 & 01010101 = 01000001$

逻辑运算

  • ||, &&, !,注意与布尔运算区别,运算的结果只有0或1(运算结果只要不为0false,就是1true);

移位运算

  • 只需注意算术右移左边填充符号位即可;

无符号数和有符号数的位级表示

  • 运算时,有符号数优先转化为无符号数;
关系表达式 运算类型 结果 说明
$0 == 0U$ unsigned True
$-1 < 0$ signed True
$-1 < 0U$ unsigned False $-1 = 1\cdots 1_2 = U_{max} > 0$
$2147483647(2^{31} - 1) > -2147483637 - 1$ signed True
$2147483647U > -2147483637 - 1$ unsigned False $-2147483637 - 1 = T_{min} \rightarrow 1\cdots 0U = 2^{31} > 2^{31} - 1$
$2147483647 > (int)2147483648U$ signed True $(int)2147483648U = 1\cdots 0 = -2^{31}$
$-1 > -2$ signed True
$(unsigned)-1 > -2$ unsigned True $(unsigned)-1 = U_{max}$
  • 数据类型只决定读取方式,不改变存储方式(01串);
  • 一些另外的注意点:sizeof()返回的类型为unsigned int,所以以下代码会导致死循环:

位扩展和位截断

Sign Extension

  • 根据最高位决定补0或者补1;

Sign Truncation

  • 无符号数截断$B2U_k(x_{k-1}\cdots x_0) = B2U_w(x_{w-1}\cdots x_k x_{k-1}\cdots x_0) % 2^k$
  • 有符号数截断$B2T_k(x_{k-1}\cdots x_0) = U2T_w(B2U_w(x_{w-1}\cdots x_k x_{k-1}\cdots x_0)%2^k)$,即先截断,再重新解释;
  • 例子:

    解答:
1
2
3
4
short si = 0x 80 00 = -32768;
unsigned short usi = 0x 80 00 = 32768;
int i = 0x FF FF 80 00 = -32768;
unsigned ui = 0x 00 00 80 00 = 32768;


解答:

1
2
3
int i = 0x 00 00 80 00 = 32768;
short si = (short)i = 0x 80 00 = -32768;
int j = si = 0x FF FF 80 00 = -32768;

CSAPP 学习随笔(2):Bits-ints-part1
https://blog.yokumi.cn/2025/01/04/CSAPP 学习随笔(2):Bits-ints-part1/
作者
Yokumi
发布于
2025年1月4日
许可协议
CC BY-NC-SA 4.0