CS61C C Note
揭示C语言的本质
- Array在传递给函数时记得必须要一并传递Array的大小,因为在函数内使用
sizeof
会得到不正确的结果。 - Array in C don’t know their size.
- 数组名不是一个变量。
- Struct Alignment.
- A String in C is just an array of characters.
- String end. Last character is followed by a 0 byte(‘\0’)(a.k.a
null terminator
). strlen()
return the length of string(not including null term).- Pointer Arithmetic, Pointer+1实际上是加指针指向的类型的大小
sizeof(*p)
. Pointer arithmetic moves the pointer by the
size of the thing it’s pointing to. - 注意
postfixal
++的优先级要大于dereference(*), 注意这两种区别*p++
,先将p和后置++捆绑,但是在解引用之后生效,即增以p=p+1。(*p)++
表示,先将p和*
捆绑,再将解引用后的值++, 即(*p) = (*p) + 1. - 声明一个指针如果未初始化,则随机指向任何一个地址
garbage
,这在dereference
时会发生ACV(如果地址为系统地址)。 - dot notation & arrow notationss
- pointers to pointers, 还有一点需要注意。如果传的参数不是当前类型本身的地址,则在函数中改变的值不会对全局造成影响,比如:类型本身是指针就需要传递指针的指针才能改变本身的值。
- Stack frame, which contains location of caller function(调用函数的入口地址)、function arguments(函数参数)、Space for local variables(局部变量所需的空间). Actually in xv6, it contains the additional part of previous stack frame pointer.
- Stack pointer 为最低的(current)Stack frame.
- 注意从局部变量返回地址,这个地址在接下来主函数中解引用会出现错误的值,因为栈帧(stack frame)很可能会被覆盖(over write)。印象中Effective cpp书中只是提到这种情况是危险的但并未说清楚其中的原理。So never return pointers to local variable from function.
- Static Data: place for variables that persist. 静态数据会在程序执行的整个过程中持续存在。
String literal
字符串字面量同样也是静态数据,比如:char* str = "hi"
, 为一个字符指针指向用引号括起来的字符串。切记不要误用为char str[] = "hi"
,它会将数据保存到栈(stack)中而不是Static Data
区域。String literal
是不能被更改的左值。Static Data
由两种类型组成,一种是Read-only
, 比如说String literal
; 一种是Read-Write
, 比如说Global variable
.Code
为Read-only
Data,存放machine code.- 地址大小即为指针的大小,取决于Architecture.
Endianness
, Big Endian or Little Endian, which just are used in Memory.sizeof(type/var)
函数输出类型的字节大小。malloc(n)
函数,分配n个bytes连续的未初始化的虚存,返回分配块的起始地址(void*类型)。搭配typecaset和sizeof使用,case:int *p = (int *) malloc(n*sizeof(int));
, 注意如果为字符串(字符数组)分配空间size则需要+1,为null terminator分配一个location.calloc(nmember, size)
和malloc
一致, 只多了一步初始化为0
.nmember
为成员的数量,size
为每个成员的大小。realloc(ptr, size)
,ptr
为malloc
或calloc
返回的指针,size
为需要改变的所需要的大小(同malloc),会复制起始地址为ptr
的内容。且可能会移动地址,或者保持在ptr
原来的地址不变。free(p)
函数,p必须为最开始分配时的起始地址,否则会抛出异常,因此对p++
操作是不明智的。注意free
的释放顺序,应该最后释放源,否则可能会double free。- Memory Error: Segmentation Error、Bus Error.
strcpy()
的修订版本strncpy
保证dst
有足够的空间供src
来copy.- Rule of Thumb(经验法则): Malloc的数量超过free意味着内存泄漏;潜在的内存泄漏:改变指针。
free()
adds block to the list, combines with adjacent free blocks;malloc()
searches free list for block large enough to meet request- Choose block in malloc(): Best-fit, First-fit, Next-fit.