MIT6.S081笔记:lecture 2 introduce to C
MIT6.S081笔记:lecture 2 introduce to C
Materials learning
What is different about C? (vs. Python)
C是一个高级汇编语言
- 其代码直接对应于机器指令
- python dict相反,会使用很多隐藏于之下的code
C是编译而不是解释的
- 可以直接在解释器上执行,非常快
C是静态类型的
python中,在变量中,类型与变量值相关联:
每个值存于一个内存区域中,这个区域包含了这个值的类型相关信息
C中,类型与变量相关联,并解释为字节值:
值并不包含任何类型信息,所有信息均存于变量
类型错误在编译时被捕获
C使用手动内存管理,没有垃圾收集机制
- 显示的“malloc”和“free”,直接访问内存
- 更快,也更容易出现错误
C中的Intergers和floats有特定的但不明确的边界
不同的类型在不同的平台有着不同的涵义(同为int可能机器不一样,所表示的范围也就不一样)
大端和小端
怎样在内存中表示:number like 0x12345678 (= 305419896) ?
- RISC-V platform is little-endian
C中的内存类型
堆内存
动态内存,需要显示分配(未初始化过的)
静态内存
- 在任何函数之外定义的变量,以及通过static声明的变量
- 只有单个的拷贝,被存储在了一个预先定义且不会改变的内存地址
- 初始化为0
栈内存
- 函数中的局部变量
- 未初始化
Key topic in C :内存安全
- use after free
- double free
- uninitialize memory
- buffer overflow
- memory leak
- type confusion
Key topic in C:指针
- 指针本质上是int,它表示的是变量所在的内存地址
- 不同类型的指针如上图
- 指针的大小
- 与特定平台相关
- RISC-V使用64bit指针(与long大小相同)
- This means, in 6.S081, we can cast a pointer to a long, but not to an int.
C中的数组
- 固定大小
- 在内存中连续存储:
定义 v.s. 声明
C中的声明是必须的,C需要其类以及类型签名
- If it hasn’t seen a declaration yet, it won’t know the correct types to use.
定义在代码中只能出现一次
通常情况下,会把声明放在单独的头文件里
定义静态函数和变量
- 如果一个函数在两个文件中出现,他们会发生冲突。
- 为了避免冲突,可以使用static关键字
1 | static void function_2(int xyz); |
- 上面的函数只可以在当前定义的文件中使用
- 也可以在局部变量上声明static关键字:
1 | int add_cumulative_numbers(int increase) { |
在调用的初次会被初始化为0,并且会保存其值
作为函数指针:
1 | static void my_function_1(int); |
C中的字符串
- 尾字符为
'\0' = (0x00)
。注意,其值为0 - 计算字符串的长度:
1 | int strlen(const char *str) { |
类型定义
- 类型别名:
1 | // from kernel/types.h: |
- 方便使用+更加清楚
- 跨平台:If we ever port xv6 to another platform where the sizes don’t match up like this, we can just change the one file that defines these typedefs, and the rest of the code will update to match!
头文件和源文件
- 头文件包含用来共享的声明
- 源文件包含不同代码的定义,如:
1 | // kernel/spinlock.h: declarations describing the spinlock interface |
C预处理器
- 常见预处理指令:
1 |
|
1 |
|
1 |
Include Guard
1 | // at the start of the something.h file |
常见内存函数
- malloc(n): 返回分配内存的首地址
- free(ptr)
- memset(ptr,v,n):set every byte from ptr[0] to ptr[n-1] to v
- memmove(dst, src, n): copies src[0]…src[n-1] to dst[0]…dst[n-1]
- memcpy(dst, src, n): (Discouraged! Prefer memmove.)
常见字符串操作函数
- strlen(str)
- strcmp(a,b)
- strcpy(dst, src)
一定要记住NULL终结符
Unions
1 | union my_union { |
- only safely use a single field of a union at a time
- You won’t need these much.
C位操作
1 | unsigned int my_int; |
Finally: a pointer challenge
1 | Source: The Ksplice Pointer Challenge - Oracle Linux Blog |
Exercise testing
- Post title:MIT6.S081笔记:lecture 2 introduce to C
- Post author:sixwalter
- Create time:2023-08-05 11:14:26
- Post link:https://coelien.github.io/2023/08/05/course-learning/MIT6.S081/lec2/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
Comments