Harvard CS50 学习笔记(四)
目录
摘要
Harvard CS50 学习笔记(四)。
4 Memory
4.1 Lecture
4.1.1 Storing finite information
4.1.2 Pixel art
4.1.3 RGB
4.1.4 Hexadecimal
16进制一般前面有0x,用于与10进制区分。0x11=17
4.1.5 Memory addresses
4.1.6 address.c
4.1.7 Pointers
- 指针,是用于记录值的内存地址变量。
4.1.8 Declaring pointers
-
单个
&,是address operator(地址运算符)。 -
&i表示取变量i的地址。 -
*表示要记录指针(声明指针变量)。1 2 3 4int n = 50; // 定义一个指向int型的指针变量p,并用n的地址来初始化p int *p = &n; printf("%p\n", p);
参考
4.1.9 “Address of”
4.1.10 Dereference operator
- deference operator(引用解析运算符)——
*。 - reference——(变量的引用)。
- dereference——其实就是de(反)- reference(引用),即**(指针的)变量**。
- 一个
*,表示我们要获取reference(引用),即地址值。 - 再加一个
*,表示我们要反引用,也译为解引用,就是获取那个引用(地址)所储存的值(获取到之后其实可以改变地址所存储的值)。
4.1.11 Visualizing pointers
- 现在指针一般都是8字节(64比特)。
4.1.12 Assignment operators
C中,不会自动做什么事情。- 如果有一个变量
n =50,其指针为p =0x123。 - 此时创建一个新变量
c = n,p不会有任何变化。
4.1.13 Strings in memory
- 字符串变量,实质为指向第一个字符地址的指针。
4.1.14 char *
string s = "HI!";等同于char *s = "HI!";
4.1.15 Different Variables with Different Pointers
- 为什么打印的结果不同?
4.1.16 address.c
- 结果不同的原因解析:
- 右边比较好理解,字符串变量的地址,与字符串第一个字符的地址相同。
- 左边的关键在于,第
7行,把字符串的第一个字符H,赋值给了一个新的变量c,此操作在内存里进行了复制,也就是内存中多了一个新的变量c,在不同的位置,储存着与字符串第一个字符相同的字符H。 - 再打印变量
c的地址,自然与字符串变量s的地址不同。
4.1.17 Pointers to array values
- 左图比较好理解。
- 为什么右图的第
22行打印出了不一样的地址?因为那是指针的地址。 - 基本类型如果要获取地址值,需要在变量名前加
&。 - 数组与字符串(底层就是数组)不需要。
4.1.18 Defining strings
<cs50.h>中的string类型实质为typedef char *string;
4.1.19 Pointer arithmetic
- 注意,这里的
+1操作,加了4个字节,因为一个int占4字节,而不是加1个字节或1个比特,编译器帮我们处理了。
4.1.20 Arrays as pointers
- 还是上图,此处并没有用
&符号来表示数组的地址,但打印的时候,却使用了*符号来解析地址。 - 因为可以把数组的变量名,直接作为指针使用。
- 即可以把数组,当作指向其第一个元素的指针。
4.1.21 Comparing integers
4.1.22 Comparing strings
4.1.23 Copying values
4.1.24 malloc and free
malloc()申请内存。free()释放内存。- 需要
#include <stdlib.h> - 实际上,这个
malloc()就相当于Java里面的new一样,只是Java把各种细节给你封装抽象成一个new,GC会自动给你回收,不需要自己去free()。
4.1.25 Copying with malloc and free
4.1.26 Valgrind
- 检查与内存相关的潜在BUG。
4.1.27 Garbage values
- 不初始化,就会有无法预测的垃圾值。
4.1.28 Binky Pointer Fun
- 试图deference(引用解析)垃圾值,会造成错误。
4.1.29 Swap
4.1.30 swap.c
- 没有传递引用,复制了值,原本的值不变。
4.1.31 Stack and heap
4.1.32 Visualizing swap.c
4.1.33 Pointers in swap.c
4.1.34 scanf
4.1.35 Segmentation fault
4.1.36 Header bytes
4.1.37 Filter
4.2 Shorts
4.2.1 Hexadecimal
4.2.2 Pointers
- 指针就是地址值。
- 指针的类型就是其指向地址值数据的类型。
- 指针必须初始化,如果初始化的事情没有明确的值,就指向空(NULL)。
4.2.3 Defining Custom Types
4.2.4 Dynamic Memory Allocation
- 一般有名字的变量在栈,没名字的在堆。
- 堆与栈实质为一块内存空间的不同部分。
- 使用
malloc()必须释放内存。 - 只有
malloc()使用的内存需要被释放(静态声明在堆的变量不需要释放)。 - 不要重复释放。
4.2.5 Call Stacks
4.2.6 File Pointers
C操作文件有抽象的数据类型,叫FILE。- 一般情况下,只要操作文件,都用文件的指针,即
FILE*。
- 文件相关的函数,都在
stdio.h里。
- 打开一个文件,即获取这个文件的指针。
- 确保
NULL的检查。 - 操作可以为
r-read,w-write,a-append。
- 关闭文件指针。
- 读字符函数。
- 获取文件的下一个字符。
- 打开文件的方式必须为
r-read。
- 可通过循环读取整个文件。
EOF表示 End Of File。
- 写字符函数。
- 将字符写入文件。
- 打开文件的方式必须为
w-wirte或a-append。
- 可通过循环读与写,实现文件复制。
- 读文件函数,参数从右往左看。
<file pointer>为文件指针,必须是读指针。<qty>读文件的数据块的数量。<size>读文件的数据块的大小(单位为字节)。<buffer>内存中的缓存区域,用于存放读到的数据,需要用指针表示(数组名本身为指针)。
- 写文件函数,参数从右往左看。
<file pointer>为文件指针,必须是写指针。<qty>读文件的数据块的数量。<size>读文件的数据块的大小(单位为字节)。<buffer>内存中的缓存区域,用于存放要写的数据,需要用指针表示(数组名本身为指针)。
4.3 Lab 4
|
|
4.4 Problem Set 4
4.4.1 FIlter
|
|
4.4.2 Recover
|
|