zoukankan      html  css  js  c++  java
  • 深入理解C/C++二维数组

    深入理解C/C++二维数组

    前言

    本来以为自己对二维数组的理解还可以,没感觉有什么,但是今天小伙伴问了一个问题感觉迷惑了好久,于是决定细致的记录一下,一步一步的探究各种关于二维数组的问题,巩固基础。

    二维数组的探究之旅(初级)

    首先定义二维数组

    int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    

    然后开始研究二维数组名和地址的关系

    // 打印a a[0] 和 a[0][0]的地址
    cout << "the value of a: " << a << endl;
    cout << "the value of a[0]: " << a[0] << endl;
    cout << "the address of a[0][0]: " << &a[0][0] << endl;
    
    the value of a: 0x7ffe5b8c1ee0
    the value of a[0]: 0x7ffe5b8c1ee0
    the address of a[0][0]: 0x7ffe5b8c1ee0
    

    就如各种资料说的那样,可以看出三个表达指向的是一个地址,继续看

    这里看一下每一行(a[i], 0leq i<3)

    for (int i = 0; i < 3; ++i)
        cout << "the value of a[" << i << "]" << " is " << a[i] << endl;
    
    the value of a[0]is 0x7ffe5b8c1ee0
    the value of a[1]is 0x7ffe5b8c1eec
    the value of a[2]is 0x7ffe5b8c1ef8
    

    打印的结果是每一行的首地址,可以看出来每两个地址之间差12个字节,也就是三个int的长度(每个int是四个字节,大部分编译器是这样的)。这与我们预期的是一样的,毕竟是每行的首地址。

    继续走,我们看到(a, a[0], a[0][0])的地址是一样的,都是最头上的首地址,那么这里用这个地址推导进而显示其他位置的元素

    // 由a[0]推出其他,这里以第1行第1列(0 base)为例
    cout << "the address of a[0+1]+1 " << "is " << a[0+1]+1 << endl;
    cout << "the value of a[0+1]+1 " << "is " << *(a[0+1]+1) << endl;
    cout << "the address of a[0]+4 " << "is " << a[0]+4 << endl;
    cout << "the value of a[0]+4 " << "is " << *(a[0]+4) << endl;
    
    the address of a[0+1]+1 is 0x7ffe5b8c1ef0
    the value of a[0+1]+1 is 5
    the address of a[0]+4 is 0x7ffe5b8c1ef0
    the value of a[0]+4 is 5
    

    前两种行是通过加a[0]的索引得到其他行的首地址,然后再加偏移量得到的,后两行是直接计算偏移量得到的。

    继续,由(a[0][0])的地址推导

    // 由&a[0][0]推出其他, 这里以第1行第1列(0 base)为例
    
    cout << "the address of a[0][0]+4 " << "is " << &a[0][0]+4 << endl;
    cout << "the value of a[0][0]+1 " << "is " << *(&a[0][0]+4) << endl;
    
    the address of a[0][0]+4 is 0x7ffe5b8c1ef0
    the value of a[0][0]+1 is 5
    

    这里和上面的第二中直接加偏移量的情况是一样的。

    由数组名得到其他元素

    现在是让人有点迷惑的地方,就是数组名a既然和(a[0], a[0][0])指向的地址一样,那么是否用法也一样呢?

    我们先来看看如何用a得到(a[1][1])

    // 假设要求a[1][1](5)
    cout << "a[1][1] inferred from a : " << *(*(a+1)+1) << endl;
    
    a[1][1] inferred from a : 5
    

    a+1指向的是(a[1]),这里是第1行(0 base)的首地址,对它解引用得到a[1]的地址,然后+1就得到(a[1][1])的地址了。

    前面说a+1是指向地址的,那么是不是意味a是一个二级指针呢?

    int *p = a; // 不通过
    

    实验发现报错,说明a不是一个指针类型,继续看

    int *p = *a;
    cout << "the value of p is: " << p << endl;
    cout << "the value of *p is: " << *p << endl;
    cout << "the value of p+1 is: " << p+1 << endl;
    cout << "the value of *(p+1) is: " << *(p+1) << endl;
    
    cout << "a[1][1] inferred from p : " << *(p+1*3+1) << endl;
    
    the value of p is: 0x7ffe5b8c1ee0
    the value of *p is: 1
    the value of p+1 is: 0x7ffe5b8c1ee4
    the value of *(p+1) is: 2
    a[1][1] inferred from p : 5
    

    对a解引用后确实是一个地址,所以可以定义指针,并且可以用加偏移量的方式得到(a[1][1])

    更为有趣的是

    cout << "a[1][1] inferred from p[] : " << p[1*3+1] << endl;
    
    a[1][1] inferred from p[] : 5
    

    指针p表现的竟然像一个一维数组(因为直接按索引就可以得到元素),这里也增加了一种新的取元素方式。这可能和[]的工作方式有关,这部分还是没弄明白,欢迎指导。

    总结

    这篇博客详细的记录了由二维数组名引出的各种细节,虽然还不完善,但是确实让自己巩固了基础,以后估计应该不会倒在二维数组了……吧。

  • 相关阅读:
    汇编基础概念
    linux实验小结
    乐视三合一体感摄像头开发记录
    IplImage* 格式与Mat 格式的转换
    STM32关于优先级设定的理解 NVIC_SetPriority()
    "IRQn_Type" is undefined
    串口通信实验编译没有错误,但是串口调试助手收不到数据
    SecureCRT 8版本 自用备份
    Matlab使用robot Toolbox
    开篇
  • 原文地址:https://www.cnblogs.com/bobxxxl/p/10438034.html
Copyright © 2011-2022 走看看