
书: https://pan.baidu.com/s/15VfTw9eJ2MoiHktwswP0gw?pwd=tq5x
笔记如下:
一、指针本质
- “指针的本质是地址的容器——
int *p
中p
存储的是内存地址,*p
是解引用该地址的值。” - “指针的类型(如
char*
与int*
)决定指针算术运算的步长(p+1
偏移量分别为1字节和4字节)。”
二、指针与数组
- “数组名在多数表达式中退化为指向首元素的指针,但
sizeof(arr)
和&arr
是例外(保留数组类型信息)。” - “
int a[10];
中,a
与&a
的数值相同,但类型不同(int*
vsint(*)[10]
),指针运算结果迥异。”
三、动态内存管理
- “
malloc
分配的内存未初始化,calloc
初始化为零,realloc
调整大小可能移动内存块。” - “内存泄漏的根源:
malloc
后未free
,尤其在异常路径中遗漏释放。”
四、函数与指针
- “函数指针(
int (*func)(int)
)实现回调机制,是C语言‘多态’的基础。” - “
void*
是泛型指针,但解引用前必须强制类型转换,否则行为未定义。”
五、指针高级技巧
- “二级指针(
int **p
)的典型用途:动态二维数组或修改调用函数中的指针变量。” - “
restrict
关键字(C99)告知编译器指针无重叠,允许激进优化(如memcpy
)。
六、字符串处理
- “C字符串以
\0
结尾,strlen
不计终止符,sizeof
包含终止符(如char s[]="abc"
中strlen=3
,sizeof=4
)。” - “
strcpy
与strncpy
的陷阱:后者不会自动补\0
,若源串长于目标尺寸,目标可能无终止符。”
七、结构体与指针
- “结构体指针的
->
操作符是(*p).field
的语法糖,但可读性更佳。” - “柔性数组(Flexible Array Member, C99):
struct {int len; char data[];}
允许动态分配变长结构体。”
八、预处理器与指针
- “宏函数中的指针陷阱:
#define MIN(a,b) ((a)<(b)?(a):(b))
若传入p++
会导致多次自增。”
九、调试与陷阱
- “野指针(Dangling Pointer)的成因:释放内存后未置空指针(
p = NULL
),后续访问导致崩溃。” - “
const int *p
与int *const p
的区别:前者指向常量,后者是常量指针(不可修改指向地址)。”
十、设计哲学
- “指针是C语言的灵魂,也是混乱之源——理解指针即理解C的内存模型。”
- “清晰的类型声明优于注释:
int *p
明确p
是指针,而非int* p
易误解*p
为类型。” - “指针的终极法则:永远知道它指向哪里,指向的内容是否有效。”