• C++指针解读(5)-- 指针和数组(多维数组)


    相比一维数组,二维数组的概念和相关运算要复杂得多。

    1、二维数组的存储及访问

    假设有这么一个二维数组:

    1. int arr[3][4] =
    2. {
    3. { 10, 11, 12, 13 },
    4. { 20, 21, 22, 23 },
    5. { 30, 31, 32, 33 }
    6. };

    我们可以把二维数组看成数组的数组:

    (1)包含3行:arr[0]、arr[1]、arr[2];

    (2)其中每一行是一个1维数组,它包含4个元素。

    这里,我们用arr[0]表示第一行的一维数组;用arr[1] 表示第二行的一维数组;用arr[2] 表示第三行的一维数组。

    因为在一维数组中,数组名代表首元素地址,所以arr[0]也表示一维数组arr[0]的首地址,即&arr[0][0];

    同理,arr[1]表示&arr[1][0],arr[2]表示&arr[2][0]。

    一定要记住这个重要的概念:arr[0]表示第一行的一维数组,arr[1]表示一二行的一维数组。依此类推。

    后面对二维数组的访问,都是从这个概念开始展开的。因为对二维数组元素的访问,最终还是要转化到对一维数组的访问。

    在一维数组中,指针+1就表示下一个数组元素的地址,所以arr[0]+1, arr[0]+2分别表示第2、第3个元素的地址。

    现在我们用上面关于二维数组的知识来访问二维数组中的元素:

    1. int main()
    2. {
    3. int arr[3][4] =
    4. {
    5. { 10, 11, 12, 13 },
    6. { 20, 21, 22, 23 },
    7. { 30, 31, 32, 33 }
    8. };
    9. printf("%d %d %d %d\n", *arr[0], *(arr[0] + 1), *(arr[0] + 2), *(arr[0] + 3));
    10. printf("%d %d %d %d\n", *arr[1], *(arr[1] + 1), *(arr[1] + 2), *(arr[1] + 3));
    11. printf("%d %d %d %d\n", *arr[2], *(arr[2] + 1), *(arr[2] + 2), *(arr[2] + 3));
    12. return 0;
    13. }

    现在我们可以总结下二维数组相关的指针

    表示形式

    含义

    arr

    二维数组名,二维数组元素首地址

    arr[0], *arr

    第0行的一维数组;也代表0行0列元素地址

    arr[0] + 1, &arr[0][1]

    0行1列元素地址

    *arr[0]

    0行0列元素的值,即10

    *(arr[0] + 1)

    0行1列元素的值,即11

    2、二维数组的其他访问方式

    前面我们讲到arr代表二维数组首元素的地址,因为这个二维数组由3个一维数组组成,所以arr也代表第一个一维数组的首地址。这样,arr+1就表示第二个一维数组的首地址。

    我们可以用下面的代码来验证这个结论:

    1. int main()
    2. {
    3. int arr[3][4] =
    4. {
    5. { 10, 11, 12, 13 },
    6. { 20, 21, 22, 23 },
    7. { 30, 31, 32, 33 }
    8. };
    9. printf(" %p\n", arr);
    10. printf(" %p\n", arr + 1);
    11. int gap = (char)(arr + 1) - (char)(arr);
    12. printf(" %d\n", gap);
    13. return 0;
    14. }

    从输出结果看gap是16个字节,1个整型是4个字节,4个数组元素就是16个字节。arr + 1和arr刚好差一个一维数组所占空间的字节。

    因为在一维数组中,arr[0]和*(a+0)等价,所以a[1]和*(a+1)等价,a[i]和*(a+i)等价。因此a[0]+1和*(a+0)+1都是&a[0][1]。

    这里,再把二维数组相关指针再总结一下:

    表示形式

    含义

    arr

    二维数组名;二维数组元素首地址;表示一维数组arr[0]的首地址

    arr[0], *arr, *(arr+0)

    第0行的一维数组;也代表0行0列元素地址

    arr[0] + 1, &arr[0][1], *(arr+0)+1

    0行1列元素地址

    *arr[0], *(*(arr+0))

    0行0列元素的值

    *(arr[0] + 1), *(*(arr+0)+1)

    0行1列元素的值

    arr[1]+2, *(arr+1)+2, &arr[1][2]

    1行2列元素的值

    二维数组在内存中是线性存储的,即按一维数组的方式存储,先存第1行,再存第2行。所以,我们可以按顺序方式访问二维数组。

    1. int main()
    2. {
    3. int arr[3][4] =
    4. {
    5. { 10, 11, 12, 13 },
    6. { 20, 21, 22, 23 },
    7. { 30, 31, 32, 33 }
    8. };
    9. printf(" *arr = %p ,arr[0] = %p\n", *arr, arr[0]);
    10. int* p = *arr;
    11. for (int i = 0; i < 12; i++) {
    12. printf(" %d ", *(p + i));
    13. }
    14. return 0;
    15. }

    3、指向一维数组的指针

    我们知道,指针变量必须包含它所指向的数据的类型信息,比如int *pi表示一个指向int型数据的指针变量。

    arr, arr[0]虽然指向的地址相同,但它们俩所代表的含义是不一样的。

    arr是第一个一维数组的首地址,所以arr+1就指向下一个一维数组的首地址,指针移动4*4 = 16个字节;而arr[0]是第一行第一列元素的地址,arr[0]+1下一个元素的指针,指针只移动4个字节。

    怎么定义一个指向一维数组的指针?

    int (*p)[4]

    表示一个指向一维数组的指针,这个数组含4个元素。

    注意,int (*p)[4]和int *p[4]的含义完全不同。int *p[4]表示一个数组,数组里的元素是int型指针变量。

    用一维数组指针的访问二维数组:

    1. int main()
    2. {
    3. int arr[3][4] =
    4. {
    5. { 10, 11, 12, 13 },
    6. { 20, 21, 22, 23 },
    7. { 30, 31, 32, 33 }
    8. };
    9. int(*p)[4] = arr;
    10. for (int i = 0; i < 4; i++) {
    11. printf(" %d ", (*p)[i]);
    12. }
    13. printf("\n");
    14. for (int i = 0; i < 4; i++) {
    15. printf(" %d ", *((*p) + i));
    16. }
    17. return 0;
    18. }

  • 相关阅读:
    RabbitMQ的五种常见消费模型
    面试还被问TCP?一条龙通关
    Java项目:SSM网上超市购物商城管理系统
    笙默考试管理系统-SMExamination.Model.Notice展示
    REF543KB127AAAA 支持整个企业的有效扩展规划和分析
    PyQt5 QWebEngineView网页交互
    【AGC】使用云调试优惠扣费、华为设备上触发崩溃、无法下载华为应用市场问题小结
    TikTok与人工智能:数字时代的智能互动
    基于python的毕业设计电脑硬件配置推荐系统
    FS4059B ESOP8 输入5V升压充电8.4V1.5A两串锂电池充电IC
  • 原文地址:https://blog.csdn.net/mars21/article/details/133832369