C和指针(肯尼斯·里科(KennethReek))

书: https://pan.baidu.com/s/15VfTw9eJ2MoiHktwswP0gw?pwd=tq5x
笔记如下:

一、指针本质

  1. “指针的本质是地址的容器——int *pp存储的是内存地址,*p是解引用该地址的值。”
  2. “指针的类型(如char*int*)决定指针算术运算的步长(p+1偏移量分别为1字节和4字节)。”

二、指针与数组

  1. “数组名在多数表达式中退化为指向首元素的指针,但sizeof(arr)&arr是例外(保留数组类型信息)。”
  2. int a[10];中,a&a的数值相同,但类型不同(int* vs int(*)[10]),指针运算结果迥异。”

三、动态内存管理

  1. malloc分配的内存未初始化,calloc初始化为零,realloc调整大小可能移动内存块。”
  2. “内存泄漏的根源:malloc后未free,尤其在异常路径中遗漏释放。”

四、函数与指针

  1. “函数指针(int (*func)(int))实现回调机制,是C语言‘多态’的基础。”
  2. void*是泛型指针,但解引用前必须强制类型转换,否则行为未定义。”

五、指针高级技巧

  1. “二级指针(int **p)的典型用途:动态二维数组或修改调用函数中的指针变量。”
  2. restrict关键字(C99)告知编译器指针无重叠,允许激进优化(如memcpy)。

六、字符串处理

  1. “C字符串以\0结尾,strlen不计终止符,sizeof包含终止符(如char s[]="abc"strlen=3sizeof=4)。”
  2. strcpystrncpy的陷阱:后者不会自动补\0,若源串长于目标尺寸,目标可能无终止符。”

七、结构体与指针

  1. “结构体指针的->操作符是(*p).field的语法糖,但可读性更佳。”
  2. “柔性数组(Flexible Array Member, C99):struct {int len; char data[];}允许动态分配变长结构体。”

八、预处理器与指针

  1. “宏函数中的指针陷阱:#define MIN(a,b) ((a)<(b)?(a):(b))若传入p++会导致多次自增。”

九、调试与陷阱

  1. “野指针(Dangling Pointer)的成因:释放内存后未置空指针(p = NULL),后续访问导致崩溃。”
  2. const int *pint *const p的区别:前者指向常量,后者是常量指针(不可修改指向地址)。”

十、设计哲学

  1. “指针是C语言的灵魂,也是混乱之源——理解指针即理解C的内存模型。”
  2. “清晰的类型声明优于注释:int *p明确p是指针,而非int* p易误解*p为类型。”
  3. “指针的终极法则:永远知道它指向哪里,指向的内容是否有效。”

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注