8、C 语言指针进阶总结

指针语法结构、指针与数组的多层级关系、各类特殊指针的特性及使用要点等方面,指针进阶知识

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 型指针。
  • 三类字符串存储场景
    1. 常量区字符串char *p = "hello";(只读,修改会触发段错误)。
    2. 栈区字符数组char buf[] = "hello"; char *p = buf;(可修改,p 指向栈区)。
    3. 堆区字符串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)。
  • 三大作用
    1. 修饰指针:作为 “万能指针” 接收任意类型指针(如malloc返回void*)。
    2. 修饰函数参数:void func(void)表示函数无参数。
    3. 修饰函数返回值: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 = addp = &add等价)。
    • 调用方式:p(2, 3)(*p)(2, 3)(均等价于add(2, 3))。
  • 用途:回调函数(如排序算法中的比较函数)、状态机设计等。

四、核心注意事项与易混淆点

  1. 数组指针 vs 指针数组
    • 数组指针:int (*p)[5];(指向数组的指针,本质是指针)。
    • 指针数组:int *p[5];(存储指针的数组,本质是数组)。
  1. 指针运算的偏移量:指针 + 1 的偏移量 = 指向类型的字节数(如char*偏移 1 字节,int*偏移 4 字节)。
  2. 避免野指针
    • 定义时初始化(如int *p = NULL;)。
    • 动态内存释放后置为NULLfree(p); p = NULL;)。
  1. const 的位置影响:靠近指针名则指针不可改,靠近类型则指向的内容不可改。

总结

指针进阶的核心是理解指针类型与指向数据类型的匹配性,以及不同场景下指针的语义(如数组名退化、函数名即地址)。特殊指针(如 void 指针、函数指针)拓展了指针的灵活性,但需严格遵循其使用限制。掌握多级指针与多维数组的关联、const 指针的两种形式,能有效处理复杂数据结构与内存操作,是 C 语言进阶的关键。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

長琹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值