
1. 指针的本质变量 vs 地址 vs 值这是所有混淆的根源。指针是一个变量它存储的值是内存地址。取地址符获取变量的地址。*解引用符根据地址访问该位置存储的值。int a 10; int *p a; // p 是指针变量它的值是 a 的地址 // 混淆点 printf(%p\n, p); // 输出a的地址 (例如 0x7ffd4d6a2b4c) printf(%d\n, *p); // 输出10 (a的值) printf(%p\n, p); // 输出p变量自身的地址 (另一个地址)2. 声明与解引用中的**的含义取决于上下文极易搞混。声明时int *p;这里的*是类型说明符表示p是一个“指向int的指针”。表达式中*p 20;这里的*是运算符意思是“取出p指向的内存里的值”。3.const关键字与指针const的位置是核心难点决定了谁不能被修改。声明形式含义能否修改指针指向能否通过指针修改值int *p普通指针是是const int *pint const *p指向常量的指针是否int *const p指针常量否是const int *const p指向常量的指针常量否否记忆技巧const在*左边保护的是数据*p不能变。const在*右边保护的是指针p不能变。int a 1, b 2; const int *p1 a; // 指向常量的指针 // *p1 10; // 错误不能通过p1修改a p1 b; // 正确p1可以指向别处 int *const p2 a; // 指针常量 *p2 10; // 正确可以修改a的值 // p2 b; // 错误p2不能再指向别处二、 重点与核心操作1. 指针与数组的关系这是C语言的重点也是面试常考点。数组名在大多数情况下是一个指向数组首元素的常量指针。int arr[5] {10, 20, 30, 40, 50}; int *p arr; // 等价于 p arr[0];关键区别sizeof(arr)返回整个数组占用的字节数如5 * sizeof(int)。sizeof(p)返回指针变量本身的大小通常是4或8字节。arr得到的是整个数组的地址其值与arr[0]相同但类型是int (*)[5]。2. 指针的算术运算指针加减指针的加减是以其指向类型的大小为单位的这是重中之重。int arr[5] {10, 20, 30, 40, 50}; int *p arr; printf(%d\n, *p); // 输出 10 (arr[0]) printf(%d\n, *(p 1)); // 输出 20 (arr[1])p1 实际地址增加了 sizeof(int) p; // p 现在指向 arr[1]p n的实际地址是p的地址 n * sizeof(*p)这就是为什么char *加1跳1字节int *加1跳4字节。3. 数组表示法与指针表示法的等价性arr[i]在编译时完全等价于*(arr i)。arr[2] 100; *(arr 2) 100; // 这两行代码完全等价这解释了为什么数组下标可以从0开始因为arr[0]就是*(arr 0)。三、 高级难点1. 二级指针指向指针的指针用于修改指针变量本身。cint a 10; int *p a; int **pp p; // pp 是一个指向指针p的指针 // 通过pp访问a printf(%d\n, **pp); // 输出 10 // 通过pp修改p的指向 int b 20; *pp b; // 这相当于 p b;2. 函数指针指向函数的指针用于回调函数等高级用法。cint add(int a, int b) { return a b; } int (*func_ptr)(int, int); // 声明一个函数指针 func_ptr add; // 指向add函数 int result func_ptr(3, 4); // 通过指针调用函数result 73. 动态内存分配指针是操作堆内存的唯一途径。cint *p (int*)malloc(5 * sizeof(int)); // 分配容纳5个int的内存 if (p NULL) { /* 处理错误 */ } // 使用 p 就像使用数组名一样 p[0] 1; free(p); // 务必释放内存4. 野指针、空指针与内存泄漏野指针指向无效内存的指针如已释放的内存。空指针明确指向NULL的指针表示“不指向任何地方”。内存泄漏分配了内存但忘记释放。最佳实践cint *p NULL; // 初始化时设为NULL p (int*)malloc(sizeof(int)); // ... 使用 p ... free(p); p NULL; // 释放后立即设为NULL避免野指针总结表格最易混淆的指针声明声明含义int *p指向int的指针int **p指向“指向int的指针”的指针二级指针int *p[5]指针数组包含5个int指针的数组int (*p)[5]数组指针指向一个包含5个int的数组的指针int *p()函数返回一个int指针int (*p)()函数指针指向一个返回int的函数的指针