
书: 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为类型。” - “指针的终极法则:永远知道它指向哪里,指向的内容是否有效。”