七:指针与三维数组示例

1. 三维数组中的指针

上一节中我们讨论了指针与多维数组的联系,并以二维数组举例说明了其关系。现在,我们增加一下复杂度,讨论三维数组的情况。

```
#include <stdio.h>

int main() {
    int S[2][5][10] = {
        {
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
            {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
            {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
            {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
            {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
        },
        {
            {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
            {10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
            {20, 21, 22, 23, 24, 25, 26, 27, 28, 29},
            {30, 31, 32, 33, 34, 35, 36, 37, 38, 39},
            {40, 41, 42, 43, 44, 45, 46, 47, 48, 49}
        }
    };

    // 访问元素 S[1][2][3]
    printf("S[1][2][3] = %d\n", *(*(*(S + 1) + 2) + 3));

    return 0;
}
```

让我们一步步分析表达式 `*(*(*(S + 1) + 2) + 3)` 是如何得到元素 `S[1][2][3]` 的值的。

 2. 使用指针访问三维数组元素

由于这个表达式比较长,我们按照优先级,从最内层括号开始依次计算,并将其拆分成几步来分析:

Step 1: S + 1

1. `S` 是一个类型为 `int[2][5][10]` 的数组。
2. 数组 `int[2][5][10]` 出现在表达式中,转换为 `int(*)[5][10]` 类型的指针。
3. `int(*)[5][10]` 类型的指针加1,这将指向 `S` 中的第二个 `int[5][10]`。

结果 `S + 1` 为:类型为 `int(*)[5][10]` 的指针。

Step 2: *(S + 1)

1. `S + 1` 的结果为类型 `int(*)[5][10]` 的指针。
2. 对指针使用取值运算符,`int(*)[5][10]` 转换为 `int[5][10]` 数组。

结果 `*(S + 1)` 为:类型为 `int[5][10]` 的数组。

Step 3: *(S + 1) + 2

1. `*(S + 1)` 的结果为类型 `int[5][10]` 的数组。
2. 数组 `int[5][10]` 出现在表达式中,转换为 `int(*)[10]` 类型的指针。
3. `int(*)[10]` 类型的指针加2,移动两个步长。

结果 `*(S + 1) + 2` 为:类型为 `int(*)[10]` 的指针。

 Step 4: *(*(S + 1) + 2)

1. `*(S + 1) + 2` 的结果为 `int(*)[10]` 类型的指针。
2. 对指针使用取值运算符,`int(*)[10]` 转换为 `int[10]` 数组。

结果 `*(*(S + 1) + 2)` 为:类型为 `int[10]` 的数组。

Step 5: *(*(S + 1) + 2) + 3

1. `*(*(S + 1) + 2)` 的结果为 `int[10]` 数组。
2. 数组 `int[10]` 出现在表达式中,转换为 `int*` 类型的指针。
3. `int*` 类型的指针加3,移动三个步长。

结果 `*(*(S + 1) + 2) + 3` 为:类型为 `int*` 的指针。

Step 6: *(*(*(S + 1) + 2) + 3)

1. `*(*(S + 1) + 2) + 3` 结果为 `int*` 类型的指针。
2. 对指针使用取值运算符,`int*` 转换为 `int` 整型,得到最终的结果。

结果 `*(*(*(S + 1) + 2) + 3)` 为:类型为 `int` 的整型。

验证其空间大小:

```
#include <stdio.h>

int main() {
    int S[2][5][10];

    printf("sizeof(S+1) = %zu\n", sizeof(S + 1)); // int(*)[5][10]
    printf("sizeof(*(S + 1)) = %zu\n", sizeof(*(S + 1))); // int[5][10]
    printf("sizeof(*(S + 1) + 2) = %zu\n", sizeof(*(S + 1) + 2)); // int(*)[10]
    printf("sizeof(*(*(S + 1) + 2)) = %zu\n", sizeof(*(*(S + 1) + 2))); // int[10]
    printf("sizeof(*(*(S + 1) + 2) + 3) = %zu\n", sizeof(*(*(S + 1) + 2) + 3)); // int*
    printf("sizeof(*(*(*(S + 1) + 2) + 3)) = %zu\n", sizeof(*(*(*(S + 1) + 2) + 3))); // int

    return 0;
}
```

```

// 验证类型
#include <stdio.h>

int main() {
    int S[2][5][10];
    double *p;

    p = S + 1; // int(*)[5][10]
    p = *(S + 1); // int[5][10]
    p = *(S + 1) + 2; // int(*)[10]
    p = *(*(S + 1) + 2); // int[10]
    p = *(*(S + 1) + 2) + 3; // int*
    p = *(*(*(S + 1) + 2) + 3); // int

    return 0;
}
```

报错信息提供的类型与之前分析的一致,说明我们的分析是正确的。

3. 对数组取地址

当数组名 `arr` 出现在一个表达式当中,数组名 `arr` 将会被转换为指向数组首元素的指针。但是,这个规则有两个例外:
1. 对数组名 `arr` 使用 `sizeof` 时。
2. 对数组名 `arr` 使用 `&` 时。

现在我们讨论对三维数组 `S` 取地址。

```
#include <stdio.h>

int main() {
    int S[2][5][10];
    int (*pInt2_5_10)[2][5][10] = &S;

    printf("pInt2_5_10 = %p\n", (void *)pInt2_5_10);
    printf("pInt2_5_10 + 1 = %p\n", (void *)(pInt2_5_10 + 1));

    return 0;
}
```

`pInt2_5_10` 为 `int(*)[2][5][10]` 类型的数组指针,步长为 `400`(2x5x10x4)。

  • 13
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值