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 4
int 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
|
|