1. 数据类型的用途
数据类型的本质:固定大小内存块的别名
b 和 &b 地址相等
b+1 (跳4字节) 和 &b+1 (跳数组长度字节)
b和&b所代表的数据类型不一样 -- b代表的数组首元素的地址 -- &b代表的是整个数组的地址
2.变量的本质:内存标号
3. 内存四区 -- 堆,栈,全局区(常量区),代码区
4. 函数调用模型:
5. 指针是一种数据类型,是指它指向的内存空间的数据类型。
指针的步长,根据所指内存空间类型来定。
1. 野指针:
<1> 指针变量 和 它所指向的内存空间变量是两个不同的概念。
<2> 释放了指针所指的内存空间,但是指针变量本身没有重置为NULL。
Solution:
<1> 定义指针的时候,初始化成NULL。
<2> 释放指针所指向的内存空间后,把指针重置为NULL。
2. sizeof() && strlen()
3. buf[]直接入栈,*p1指向对应常量区“xxx”,*p2指向malloc出的堆区块。
4. 两头堵算法 + 两指针字符串翻转 + 递归字符串翻转
5. 指针输入和输出:
输入:主调函数分配内存,被调函数使用。
输出:被调函数分配内存,结果通过指针做函数参数,主调函数使用。
Tip: C风格字符串有‘\0’
6. 二级指针三种内存模型
<1> 第一种内存模型:-- //指针数组 char *p[] -- p[i] + *(p+i)
打印 + 排序 - (交换的是地址)(指针的值)
<2> 第二种内存模型:-- //二维数组 char p[10][30]
打印 + 排序 – (交换的是内存块) - strcpy
<3> 第三种内存模型:-- char **p2 = (char **)malloc(sizeof(char *) *10);
i. 打印 + 排序 - (交换的是地址)(指针的值)
ii. 打印 + 排序 - (交换的是内存块) - strcpy
1. 两指针挖字符串,输入输出方法 – 二级指针最复杂场景 ---- 非常重要,尤其判断细节
2. 多维数组的本质 -- 数组的指针
<1> 二维数组在内存中是线性存储的。
<2> Memset(c, 0, sizeof(c))
3. 定义数组类型:
<1> 数组类型 (元素类型 和 数组大小决定)
typedef int (Myarray)[10];
Myarray myarray;
<2> 数组指针类型
typedef int (*PMyarray)[10];
<3> 数组指针变量
i. Myarray *myarrayPointer;
ii. PMyarray *parray;
iii. int (*PMyarray)[10];
�
4. 结构体
定义 + 初始化
5. t1.age = 10; p->age = 10;
.是寻址操作,计算age相对于t1变量的偏移量 -- 在CPU中进行,没有操作内存
6. 结构体做函数参数 -- 代码
Teacher array[3]
Teacher *pArray;
7. 结构体套一级指针 -- 加char *name
要分配内存,释放内存。每个节点!!!
8. 结构体套二级指针:
嵌套分配内存,嵌套释放内存。
1.浅拷贝:
结构体套一个一级指针或二级指针,
编译器默认只会把指针变量的值copy,不会copy指针变量所指向的内存空间。
2. 结构体中的偏移量:
一旦结构体定义了,则结构体中的成员,内存布局就确定了,可以通过age地址,求大结构体的内存地址。
3. 文件的操作 -- 读写磁盘
1. SocketClient动态库函数 -- 代码
<1> __declspec(dllexport)
<2> 将上层传递来的buf,缓存在socketClient的SCK_HANDLE结构体中。
<3> memwatch实现思路有趣