欢迎光临
我们一直在努力

一眼分清数组指针与指针数组,C 语言核心难点拆解

数组指针 vs 指针数组 完整区别总结

一、核心本质完全不同

  • 指针数组 int *arr[5] 本质:数组 数组里每一个元素都是指针变量(存放地址)。
  • 数组指针 int (*p)[5] 本质:指针 这个指针专门指向一整个数组,不是指向单个元素。
  • 二、语法区分(括号优先级关键)

    • int *arr[5]:[] 优先级高于 *,先结合成数组 arr[5],再修饰为 int * 类型,即存放int指针的数组。
    • int (*p)[5]:() 强制让 * 和变量 p 结合,p 是指针;[5] 代表它指向包含5个int元素的数组。

    三、内存占用(64位系统)

  • 指针数组 int *arr[5] 每个指针占8字节,一共5个指针:5 * 8 = 40字节 存放的是一堆地址值,不存储数据本身。 例:char *p[5] = {"hello","world"};,数组只存字符串首地址,字符串存在常量区。
  • 数组指针 int (*p)[5] 只是单个指针变量,永远占8字节,和数组长度无关。 它仅保存一整个数组的起始地址。
  • 四、加减1时的地址偏移规则(最核心差异)

    1. 指针数组元素 arr[i] + 1

    arr[i] 是普通 int*,+1 偏移单个元素大小(4字节int / 1字节char) 例:char *p[5],p[0]+1 只向后走1字节,指向下一个字符。

    2. 数组指针 p + 1

    p 指向完整数组,+1 一次性偏移整个数组总字节数 例:int (*p)[5],数组总大小5*4=20字节,p+1 地址直接+20,跳到下一个同规格数组。

    文档示例:

    int a[5] = {1,2,3,4,5};
    int (*p)[5] = &a; // &a是数组指针类型
    p + 1; // 一次性偏移整个数组20字节

    五、适用场景 & 二维数组配套用法

    1. 指针数组:处理多个字符串、字符串列表

    // 存放多组字符串常量,节省空间
    char *str_arr[3] = {"aaa", "bbb", "ccc"};
    // 传参对应形参:char *str_arr[] / char **str_arr

    对比二维字符数组 char str[3][100]:二维数组存完整字符串,占用连续字符空间;指针数组只存地址,体积更小。

    2. 数组指针:配合二维整型/字符数组传参

    二维数组数组名 a 本身就是数组指针 int (*a)[列数]

    int a[2][3] = {1,2,3,4,5,6};
    // 函数形参两种等价写法,都要求固定列数
    void print(int arr[][3], int row);
    void print(int (*arr)[3], int row);

    文档明确规则:二维数组传参必须指定列数,底层就是数组指针。

    六、取值解引用结果

  • 指针数组 arr
    • arr:数组首地址,类型 int **(二级指针)
    • arr[i]:第i个指针,类型 int *
    • *arr[i]:指针指向的int数据
  • 数组指针 p
    • p:数组整体地址,类型 int (*)[5]
    • *p:等价于数组名 a,类型 int *(首元素地址)
    • (*p)[i]:数组内第i个元素,等价 a[i]
  • 七、快速对比表格

    在这里插入图片描述

    八、一句话记忆口诀

  • 指针数组:数组存指针,char 列表专用*
  • 数组指针:指针指数组,二维数组传参专用 括号区分技巧:有括号(*p)是指针;无括号arr[]是数组。
  • 赞(0)
    未经允许不得转载:171主机测评 » 一眼分清数组指针与指针数组,C 语言核心难点拆解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址