6.S081 学习笔记 - 指针练习

练习源代码

这是 MIT 6.S081 课程中的一个指针练习,要求在第二个 Lab 前完成。

在课程的 Guidance 中是这样说的:

Unless you are already thoroughly versed in C, do not skip or skim the pointer exercises above. If you do not really understand pointers in C, you will suffer untold pain and misery in the labs, and then eventually come to understand them the hard way. Trust us; you don't want to find out what "the hard way" is.

好在看了 K&R 的书,对指针有了基本的掌握,这个练习做起来还算顺利。

一些知识点:

  • printf 中的格式化字符串 %p 用于打印指针指向的地址
  • a[i]*(a + i) 是等价的,因此 1[a] 相当于 *(1 + a),也就是 a[1]
  • 指针加 1 实际是将地址加上指针指向的类型的大小
  • 一般 int 类型是 4 字节,char 类型是 1 字节,具体因平台而异
  • AMD64RISC-V 处理器是小端序,最低有效字节存在最低地址处。如 0x12345678 在内存中的存储顺序是 0x78 0x56 0x34 0x12
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <stdio.h>
#include <stdlib.h>

void f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;

// 打印a, b, c的地址(a指向数组首个元素)
printf("1: a = %p, b = %p, c = %p\n", a, b, c);

c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i; // 数组a中的元素依次被赋值为100,101,102,103
c[0] = 200; // a[0] = 200
// a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c[1] = 300; // a[1] = 300
*(c + 2) = 301; // a[2] = 301
3 [c] = 302; // a[3] = 302
// a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c = c + 1; // 指向a[1]
*c = 400; // a[1] = 400
// a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

c = (int *)((char *)c + 1); // 指向a[0]的第一个字节
// 小端存储 500=0x1F4
// a[1] a[2]
// 90 01 00 00 | 2D 01 00 00
// c^
// 90 F4 01 00 | 00 01 00 00
// 0x1F490 = 128144, 0x100 = 256
*c = 500;
// a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);

b = (int *)a + 1; // 指向a[1],比a大4
c = (int *)((char *)a + 1); // 指向a[0]的第一个字节,比a大1
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}

int main(int ac, char **av)
{
f();
return 0;
}

输出:

1
2
3
4
5
6
1: a = 0x7ffd51350890, b = 0x55f10b7ff2a0, c = 0x7ffd51350c59
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0x7ffd51350890, b = 0x7ffd51350894, c = 0x7ffd51350891

6.S081 学习笔记 - 指针练习
http://blog.qzink.me/posts/6.S081学习笔记-指针练习/
作者
Qzink
发布于
2025年1月5日
许可协议