Chapter 5 Memory and Pointer

Pointers

Pasted image 20241006144555.png
NULL就是整数0

Structure member accessing

Pasted image 20241006150211.png
红色方框中的两种办法等效,是结构指针的访问方式。

Pasted image 20241006150602.png
答案:注意与上面的示意图做对比,同时注意,示意图中的首地址是随便编造的。
Pasted image 20241006151000.png

Question

图中是9个byte啊?为什么sizeof(pStu)是8?

sizeof(pStu)sizeof(Student *)sizeof(Student) 分别代表以下内容:

  1. sizeof(pStu):
    • pStu 是一个指向 Student 结构体的指针。在64位系统上,指针的大小是 8字节,因此 sizeof(pStu) 的结果是8。
  2. sizeof(Student *):
    • Student * 也是一个指向 Student 结构体的指针。同样地,指针在64位系统上是 8字节,所以 sizeof(Student *) 的结果也是8。
  3. sizeof(Student):
    • 这里的 Student 是一个结构体,包含了3个成员:
      • char name[4]:4个字节。
      • int born:4个字节。
      • bool male:1个字节。
        理论上,这些成员的总大小是 4 + 4 + 1 = 9字节,但由于内存对齐的原因,编译器可能会对结构体进行填充(padding),以确保数据在内存中对齐到合适的边界上。
        在你的例子中,sizeof(Student) 的结果是 12字节,这是因为编译器将 bool 类型成员之后的空隙(3字节)填充到4字节对齐。这样做的目的是为了提高内存访问的效率。
        Pasted image 20241006151640.png

Pointers of Pointers

Pasted image 20241006152055.png
注意右边代表当前方格的地址
Pasted image 20241006152205.png
同理pointer to pointer 用**就可以访问回去。

Constant pointers

注意三种对比。
Pasted image 20241006152501.png

关于记忆

Pointers and Arrays

The addresses of array elements

Pasted image 20241006153627.png

Array name

注意下面的是把一个指针当作数组来使用。
Pasted image 20241006154632.png
在C中定义一个数组时,数组名本质上是一个指向该数组第一个元素的指针常量。具体来说,students 是一个指向 Student 类型的指针,指向数组中第一个元素的地址。它的类型是 Student *
因此,students 表示的是数组第一个元素 students[0] 的地址。
为什么

Pointer arithmetic

Pasted image 20241006155433.png

int *p = numbers + 1;

numbers 的类型会被解释为 int *,指向数组的第一个元素,即 &numbers[0]。因此,numbers 在这些上下文中可以像指针一样使用。

这里的 numbers + 1 是一个指针运算。数组名 numbers 实际上是指向数组第一个元素的指针,即 &numbers[0]。而 numbers + 1 则指向数组的第二个元素(numbers[1] 的地址)。所以,p 最终指向的是 numbers[1] 的地址。

p[1] = 30;

p[1] 其实是指针的下标运算,等同于 *(p + 1)。现在 p 指向的是 numbers[2],所以 p[1] 就是 numbers[3]。因此,p[1] = 30 会将 numbers[3] 的值修改为 30。此时 numbers 数组的最终内容变为:

Differences between a pointer and an array

Pasted image 20241006170242.png
注意第三点,指针和数组的区别。
Lab4 makefile#ex1

Allocate memory: C style

Program memory

Pasted image 20241006192623.png
注意,本section开始allocate的memory全是在heap里的,看下面的例子。
Pasted image 20241006192858.png
arm64里的例子请结合上面的图示来一起看。
注意下面申请的memory,我们得到了16个字节,但是12个浪费了,用于对齐。

Memory allocation

Pasted image 20241006193248.png
注意malloc函数返回void*类型指针,而且是未初始化

具体来说,malloc 返回的地址是你可以使用的动态内存的第一个字节的地址,也就是分配的内存块的起始地址。返回的这个地址是类型为 void* 的指针,需要根据实际使用的类型进行转换。

Memory deallocation

Warning

必须自己手动释放

Pasted image 20241006193832.png
请看图中的qusetion,第一次申请的memory的地址就彻底消失了,没办法找回,浪费了内存,也没法回收了。

foo()函数也是同样的问题,p是一个局部变量,运行之后不手动free,纳闷会造成大量的memory只被申请没法释放

但是程序结束之后,操作系统会把内存重新管理,因此上面那个小程序不去释放是没什么问题的,但是在实际应用中必须要申请+释放

Allocate memory: C++ style

Operator new and new[]

Pasted image 20241006194923.png
new type会返回一个指针。
下面是其他特性。
Pasted image 20241006195123.png

Operator delete and delete[]

Pasted image 20241006195302.png- 数组内存的释放
- delete pa1;
- 虽然用于释放通过 new[] 分配的数组的内存,但这是错误的用法。应该使用 delete[] 来释放数组,否则可能导致未定义行为。
- delete [] pa2;
- 这是正确的释放通过 new[] 分配的数组内存的方式。