二级指针、函数指针、数组指针、指针数组辨析

这四个概念都涉及指针,但在声明语法内存模型使用场景上有明显区别。下面分别定义并对比。


1. 二级指针

定义:指向指针的指针,保存的是另一个指针变量的地址。

声明类型 **ptr;

示例

c

int a = 10;
int *p = &a;   // 一级指针
int **pp = &p; // 二级指针

作用

  • 在函数中修改传入的指针本身(例如动态内存分配:int *p; func(&p);

  • 管理指针数组(如命令行参数char **argv

内存模型

text

pp → p → a (10)

2. 函数指针

定义:指向函数的指针,保存函数的入口地址。

声明返回类型 (*ptr)(参数列表);

示例

c

int add(int x, int y) { return x + y; }
int (*p)(int, int) = add;   // p指向add函数
int result = p(3, 5);       // 等效于add(3,5)

作用

  • 回调函数(如qsort的比较函数)

  • 实现策略模式、状态机等

注意int *p(int, int) 是返回指针的函数,不是函数指针。


3. 数组指针

定义:指向数组的指针,强调指向整个数组,而非单个元素。

声明类型 (*ptr)[元素个数];

示例

c

int arr[5] = {1,2,3,4,5};
int (*p)[5] = &arr;   // p指向包含5个int的数组
printf("%d", (*p)[2]); // 输出3

作用

  • 操作二维数组的行指针

  • 传递固定长度的数组

区别

  • int *p = arr; → 指向首个元素,p+1指向下一个元素

  • int (*p)[5] = &arr; → 指向整个数组,p+1跳过整个数组(5个int)


4. 指针数组

定义:一个数组,其中每个元素都是指针。

声明类型 *数组名[元素个数];

示例

c

int a=1, b=2, c=3;
int *arr[3] = {&a, &b, &c};   // 存放三个int指针
printf("%d", *arr[1]);        // 输出2

作用

  • 存储字符串数组:char *strs[] = {"hello", "world"};

  • 构建二维结构的行索引

内存布局

text

arr: [ ptr_to_a, ptr_to_b, ptr_to_c ]

综合辨析对比表

概念声明示例本质常见用途
二级指针int **pp;指针的指针修改指针本身、二维动态数组
函数指针int (*fp)(int);指向代码区的指针回调、动态调用函数
数组指针int (*ap)[5];指向数组整体操作二维数组的行
指针数组int *pa[5];存储指针的数组字符串列表、多指针存储

易混淆点辨析

a) 数组指针 vs 指针数组

  • 记忆技巧:先读后面两个字——“数组指针”是“指针”(指向数组),“指针数组”是“数组”(元素是指针)。

  • sizeof

    • int (*ap)[5] → sizeof(ap)为指针大小(4/8字节),sizeof(*ap)5*sizeof(int)

    • int *pa[5] → sizeof(pa)5*sizeof(int*)

b) 二级指针 vs 指针数组

  • 二级指针常与指针数组配合使用:char **argv 可以指向 char *argv[] 的首地址。

  • 但二级指针本身只是一个变量,而指针数组是一组连续的内存空间。

c) 函数指针的语法陷阱

  • int *f(int, int); // 函数,返回int*

  • int (*f)(int, int); // 函数指针

  • 可使用typedef简化:typedef int (*Func)(int, int);


示例:综合应用

c

#include <stdio.h>

// 函数:加法
int add(int x, int y) { return x + y; }

int main() {
    // 指针数组:存放两个数组的行地址
    int row1[] = {1, 2};
    int row2[] = {3, 4};
    int *rows[2] = {row1, row2};

    // 数组指针:指向一维数组(列数固定为2)
    int (*p_row)[2] = &row1;   // 指向row1整体

    // 二级指针:指向rows指针数组的首元素
    int **pp = rows;

    // 函数指针:指向add函数
    int (*fp)(int, int) = add;

    // 使用二级指针访问二维数据
    printf("%d\n", pp[1][0]);   // 3

    // 通过函数指针调用
    printf("%d\n", fp(2, 3));    // 5

    return 0;
}

总结

名称核心要点
二级指针解引用两次才能访问原始数据
函数指针可像函数一样调用,常用于回调
数组指针移动步长是整个数组大小,多用于二维数组的行
指针数组元素都是指针,常用于存储多个地址(如字符串)

理清这些概念的关键在于区分指针本身和指针指向的对象,并通过声明语法中的括号位置加以识别:

  • [] 优先级高于 *,所以 int *p[5] 先构成数组 → 指针数组

  • (*p)[5] 用括号强制 * 先结合 → 数组指针

  • (*fp)(int) 用括号结合 * 和函数参数 → 函数指针

  • **pp 表示多级间接 → 二级指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值