
指针语法结构、指针与数组的多层级关系、各类特殊指针的特性及使用要点等方面,指针进阶知识
C 语言指针进阶核心知识点总结
一、指针语法剖析
指针的定义由指向的数据类型和指针名两部分组成,无论指针多么复杂,均可拆解为这两个核心要素。
1. 基本结构
- 语法公式:数据类型 (*指针名)[附加信息](附加信息如数组长度、函数参数列表等)。
- 解析逻辑:先确定指针名,再根据运算符优先级判断指向的数据类型。
2. 常见复杂指针示例
|
指针定义 |
指向的数据类型 |
指针类型名称 |
说明 |
|
char *p1; |
char |
一级字符指针 |
指向单个字符 |
|
char **p2; |
char * |
二级字符指针 |
指向一级字符指针 |
|
char (*p4)[5]; |
char [5] |
数组指针 |
指向包含 5 个字符的数组 |
|
char (*p5)(int, char); |
char (int, char) |
函数指针 |
指向参数为(int, char)、返回char的函数 |
二、指针与数组的多层级关系
指针与数组的关联随维度提升而复杂化,核心是指针类型需与数组元素类型匹配,以确保地址偏移正确。
1. 1 级关系(一维数组)
- 数组与指针对应:一维数组名是首元素指针,可用一级指针指向。
|
int buf[5] = {1,2,3,4,5}; int *p = buf; // p指向buf[0],p+1偏移4字节(int大小) |
- 值访问:buf[i]等价于*(p+i)。
2. 2 级关系(二维数组)
- 数组与指针对应:二维数组名是首行(一维数组)的指针,需用数组指针指向。
|
int buf[2][3] = {{1,2,3}, {4,5,6}}; int (*p)[3] = buf; // p指向首行(buf[0]),p+1偏移12字节(3个int) |
- 值访问:buf[x][y]等价于*(*(p+x)+y)。
3. 3 级关系(三维数组)
- 数组与指针对应:三维数组名是首 “块”(二维数组)的指针,需用三维数组指针指向。
|
int buf[2][2][3] = {{{1,2,3},{4,5,6}}, {{7,8,9},{10,11,12}}}; int (*p)[2][3] = buf; // p指向首块,p+1偏移24字节(2×3个int) |
- 值访问:buf[x][y][z]等价于*(*(*(p+x)+y)+z)。
三、特殊指针类型及特性
1. char 型指针(与字符串紧密关联)
- 核心特性:char 型指针是字符串操作的核心,因字符串本质是字符数组,数组名退化为 char 型指针。
- 三类字符串存储场景:
- 常量区字符串:char *p = "hello";(只读,修改会触发段错误)。
- 栈区字符数组:char buf[] = "hello"; char *p = buf;(可修改,p 指向栈区)。
- 堆区字符串:char *p = malloc(10); strcpy(p, "hello");(可修改,需手动释放内存)。
2. 多级指针
- 定义:指向指针的指针,n 级指针存储(n-1)级指针的地址。
|
int num = 100; int *p1 = # // 一级指针:指向num int **p2 = &p1; // 二级指针:指向p1 int ***p3 = &p2; // 三级指针:指向p2 |
- 值访问:***p3等价于num(每级解引用对应一层指针)。
- 用途:处理指针数组、函数参数传递指针的地址等(如动态二维数组)。
3. void 型指针(万能指针)
- 定义:void *p;(指向类型未知的数据)。
- 核心限制:
- 不可直接解引用(*p错误),需强制类型转换(如*(int*)p)。
- 不可直接加减(偏移量未知),转换为具体类型后才可运算(如(int*)p + 1)。
- 三大作用:
- 修饰指针:作为 “万能指针” 接收任意类型指针(如malloc返回void*)。
- 修饰函数参数:void func(void)表示函数无参数。
- 修饰函数返回值:void func()表示函数无返回值。
4. const 型指针(常量指针与常量目标指针)
(1)常量指针(指针本身不可改)
- 定义:类型 *const 指针名;(const 修饰指针名,指针存储的地址不可变)。
|
int num = 100; int *const p = # // p不可指向其他地址 *p = 200; // 合法:指向的内容可改 // p = &other; // 错误:指针本身不可改 |
(2)常量目标指针(指向的内容不可改)
- 定义:const 类型 *指针名; 或 类型 const *指针名;(const 修饰指向的类型,内容不可通过该指针修改)。
|
int num = 100; const int *p = # // 或 int const *p = # p = &other; // 合法:指针本身可改 // *p = 200; // 错误:指向的内容不可通过p修改 num = 200; // 合法:可通过变量直接修改 |
5. 函数指针(指向函数的指针)
- 定义:返回值类型 (*指针名)(参数类型列表);
|
int add(int a, int b) { return a + b; } int (*p)(int, int) = add; // p指向add函数 |
- 特性:
- 函数名本身就是地址(p = add与p = &add等价)。
- 调用方式:p(2, 3)或(*p)(2, 3)(均等价于add(2, 3))。
- 用途:回调函数(如排序算法中的比较函数)、状态机设计等。
四、核心注意事项与易混淆点
- 数组指针 vs 指针数组:
- 数组指针:int (*p)[5];(指向数组的指针,本质是指针)。
- 指针数组:int *p[5];(存储指针的数组,本质是数组)。
- 指针运算的偏移量:指针 + 1 的偏移量 = 指向类型的字节数(如char*偏移 1 字节,int*偏移 4 字节)。
- 避免野指针:
- 定义时初始化(如int *p = NULL;)。
- 动态内存释放后置为NULL(free(p); p = NULL;)。
- const 的位置影响:靠近指针名则指针不可改,靠近类型则指向的内容不可改。
总结
指针进阶的核心是理解指针类型与指向数据类型的匹配性,以及不同场景下指针的语义(如数组名退化、函数名即地址)。特殊指针(如 void 指针、函数指针)拓展了指针的灵活性,但需严格遵循其使用限制。掌握多级指针与多维数组的关联、const 指针的两种形式,能有效处理复杂数据结构与内存操作,是 C 语言进阶的关键。
1194

被折叠的 条评论
为什么被折叠?



