C代码指针

这段C代码主要演示了sizeof运算符在指针数组中的行为。理解的关键在于分析int *a[2][3]的类型和sizeof在不同解引用层级下的计算方式。以下是逐行解析:

#include <stdio.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    //int a[2][3]={0};
    int *a[2][3];
    printf("sizeof(a)  =%d \n",sizeof(a));
    printf("sizeof(*a)  =%d\n",sizeof(*a));
    printf("sizeof(**a)  =%d\n",sizeof(**a));
    printf("sizeof(***a)  =%d\n",sizeof(***a));
    //printf("szieof(a) = %d,szieof(*a) = %d,szieof(**a) = %d,szieof(***a) = %d",szieof(a),szieof(*a),szieof(**a),szieof(***a));
    return 0;
}

1. 变量声明

int *a[2][3];
  • 声明了一个2行3列的二维数组a
  • 每个元素都是int*类型(指向整数的指针)
  • 内存结构:6个连续的指针元素(2×3)

2. sizeof运算解析

表达式实际类型计算方式32位系统64位系统
sizeof(a)int*[2][3]整个数组大小 = 2×3×指针大小24字节48字节
sizeof(*a)int*[3]单行大小 = 3×指针大小12字节24字节
sizeof(**a)int*单个元素大小 = 指针大小4字节8字节
sizeof(***a)int指针解引用后的大小 = sizeof(int)4字节4字节

3. 关键概念图解

a → [ ptr00 ] → (可能的int数据)
   | [ ptr01 ] → ...
   | [ ptr02 ] → ...
   | [ ptr10 ] → ...
   | [ ptr11 ] → ...
   | [ ptr12 ] → ...
  • a:整个二维数组(6个指针)
  • *a:第一行(3个指针)
  • **a:第一行第一个元素(单个指针)
  • a*:指针指向的整数数据

4. 输出结果说明

  • sizeof(a):计算整个二维数组的空间占用
  • sizeof(*a):计算单行(子数组)的空间占用
  • sizeof(**a):计算单个指针元素的大小
  • sizeof(***a):计算指针解引用后的整数大小

5. 系统差异

  • 32位系统:指针占4字节,int占4字节
  • 64位系统:指针占8字节,int仍占4字节
  • 输出差异主要来自指针大小的不同

总结

这段代码展示了指针数组在内存中的层级结构:

  1. 二维数组 → 2. 行数组 → 3. 单个指针 → 4. 实际数据
    通过sizeof运算符可以清晰地观察到:
  • 数组整体与部分的空间关系
  • 指针与数据的本质区别
  • 系统架构对指针大小的直接影响

理解核心:sizeof在编译时静态计算类型大小,与实际存储的值无关。这种分析方式对于理解复杂指针结构和内存管理至关重要。

C代码指针》有一个想法

  1. me

    理解 int *a[2][3] 及其相关表达式,关键是拆解变量类型和指针运算的关系,一步步来会很清晰 👇
    第一步:明确 int *a[2][3] 是什么?
    · 优先级规则:[] 比 * 优先级高,所以这是一个 二维数组,而非指针。
    · 数组类型:数组的每个元素是 int*(指向 int 的指针)。
    ·维度:2 行 × 3 列,共 2×3=6 个元素,每个元素都是一个 int* 指针。
    简单说:a 是一个「存储指针的二维数组」,像个 2 行 3 列的表格,每个格子里放着一个指向整数的地址。
    第二步:关键表达式解析
    1. a
    · 类型:int* (*)[3](指向「包含 3 个 int* 元素的数组」的指针)。
    · 含义:数组名 a 代表数组首元素的地址。由于 a 是二维数组,其首元素是第一行(一个包含 3 个 int* 的一维数组),所以 a 是指向「行数组」的指针。
    2. *a
    · 类型:int* [3](包含 3 个 int* 元素的一维数组)。
    · 含义:对 a 解引用,得到二维数组的第一行(完整的一维数组)。此时 *a 等价于 a[0](第一行的数组名)。
    3. **a
    · 类型:int*(指向 int 的指针)。
    · 含义:先 *a 得到第一行数组,再对其解引用,得到该行的第一个元素(即 a[0][0],一个 int* 指针)。
    4. a[0][0](补充:和 **a 等价)
    · 直接通过数组下标访问第一行第一列的 int* 指针,与 **a 完全相同。
    5. *a[0][0](补充:访问最终的 int 值)
    · 如果想获取 a[0][0] 指针指向的整数,需要再解引用一次:*a[0][0](或 ***a,但不推荐这么写,可读性差)。
    总结:从 a 到具体值的路径
    a → 指向第一行的指针(行指针)
    *a → 第一行数组(a[0])
    **a → 第一行第一个指针(a[0][0],int* 类型)
    ***a → a[0][0] 指向的整数(int 类型)
    可以类比成:
    a 是「书架」的地址 → *a 是第一层书架 → **a 是第一层第一个格子里的「书签」(指向某页)→ ***a 是书签指向的「具体内容」。
    避坑提醒
    · 区分 int *a[2][3](指针数组的二维数组)和 int (*a)[2][3](指向二维数组的指针),前者数组元素是指针,后者本身是指针。
    · 多维数组的指针运算容易绕,建议多结合下标(如 a[i][j])理解,少用多层解引用(如 ***a)。
    如果觉得抽象,画个内存布局图会更直观哦!需要的话可以告诉我,帮你补充~ 😊

    回复

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注