C|二维、三维数组的多种遍历方法

技术博客 (75) 2023-12-04 09:01:01

对于数组,与指针变量总有千丝万缕的关系。

    int arr[3][4] = {
        1,2,3,4,
        5,6,7,8,
        9,10,11,12};
    int base;   // 以下三个地址值相同,但类型不同,尺寸不一
    printf("%p\n",&arr);                  // 0012FF18
    printf("%p\n",arr);                   // 0012FF18
    printf("%p\n",arr[0]);                // 0012FF18
    printf("%p\n",&arr[0][0]);            // 0012FF18
    //取值需要不同级别的解引用
    printf("%d\n",**arr);                 // 1
    printf("%d\n",*arr[0]);               // 1
    printf("%d\n",arr[0][0]);             // 1

    printf("%p\n",base=(int)&arr[0][0]);  // 0012FF18
                                          // +1的偏移值是其类型尺寸的偏移
    printf("%d\n",(int)(&arr+1)-base);    // 48  sizeof(int)*4*3
    printf("%d\n",(int)(arr+1)-base);     // 16  sizeof(int)*4
    printf("%d\n",(int)(arr[0]+1)-base);  // 4   sizeof(int)
    printf("%d\n",(int)(&arr[0][0])-base);// 0

一级指针,可以用一维数组名赋值。

而对于多维数组,与多级指针就不存在等价关系了。

对于n维数组,可以直接用一级指针去处理,因为n维数组在内存中也是线性存储的。

另外,n维数组,可以理解为其元素是n-1数组,这样,n维数组就可以用n-1维数组指针来表示。也可以用指针数组(其指针指向一个n-1维数组)来表示。所以从这个意义上说,这是一种降维的处理方式,对于符号“*”与“[]”,不是很严格地可以理解为有一定的等价性:

#include <iostream>
using namespace std;

int main()
{
    int arr[3][4] = {
        1,2,3,4,
        5,6,7,8,
        9,10,11,12};
  
    int i,j;

    cout<< "1 二维数组下标遍历"<<endl;
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++) // 以下四种写法等价
            // cout<<arr[i][j]<<"\t";
            cout<<*(arr[i]+j)<<"\t";
            // cout<<*(*(arr+i)+j)<<"\t";
            // cout<<(*(arr+i))[j]<<"\t";
        cout<<endl;
    }

    cout<<"2 二维数组看作线性一维来遍历"<<endl;
    for(i=0;i<3*4;i++)
    {
        cout<<*(*arr+i)<<"\t";
        if((i+1)%4==0)
            cout<<endl;
    }

    cout<< "3 数组指针遍历二维数组"<<endl;
    int (*ap)[4] = arr; // 行指针ap,指向arr每行的首地址
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++)  // 以下四种写法等价
            cout<<ap[i][j]<<"\t";
            //cout<<*(ap[i]+j)<<"\t";
            //cout<<*(*(ap+i)+j)<<"\t";
            //cout<<(*(ap+i))[j]<<"\t";
        cout<<endl;
    }

    cout<< "4 指针数组遍历二维数组"<<endl;
    int* pa[3];
    for(i=0;i<3;i++)
        pa[i]=arr[i];     // 指针数组的元素是每行的首地址
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++)  // 以下二种写法等价
            cout<<pa[i][j]<<"\t";
        cout<<endl;
    }

    cout<< "5 一级指针遍历二维数组"<<endl;
    int* p;  // 以下四种写法等价
    p = (int*)arr;
    p = &arr[0][0];
    p = arr[0];
    p = *arr;
    for(i=0;i<3;i++)
    {
        for(j=0;j<4;j++)  // 以下二种写法等价
            cout<<*(p+i*3+j)<<"\t";
            //cout<<(p+i*3)[j]<<"\t";
        cout<<endl;
    }
    for(i=0;i<3*4;i++)
    {
        //cout<<p[i]<<"\t";
        cout<<*(p+i)<<"\t";
        if((i+1)%4==0)
            cout<<endl;
    }
    while(1);
    return 0;
}

数组指针也可以指向一维数组,但写法细节略有区别:

    int a[4] = {11,22,33,44};
    cout<<&a[0]<<endl; // 一维数组首地址
    cout<<a+1<<endl;   // +1是偏移一个元素
    cout<<&a+1<<endl;  // +1是偏移整个数组的长度
    int (*p1)[4] = &a;
    cout<<(*p1)[2]<<endl; // 33
C|二维、三维数组的多种遍历方法 (https://mushiming.com/) 技术博客 第1张

三维数组的遍历:

#include <iostream>
using namespace std;

int main()
{
    int arr[2][3][4] = {0};
    int* p = (int*)arr;
    int i,j,k;
    for(i = 0; i<2*3*4; i++)
        *p++ = i+1;
    p= arr[0][0]; // p = &arr[0][0][0];
    for(i=0;i<2;i++)
    {
        for(j=0;j<3;j++)
        {
            for(k=0;k<4;k++)  // 以下5种方式等价
                //cout<< arr[i][j][k] <<" ";
                //cout<< *(arr[i][j]+k) <<" ";
                //cout<< *(*(arr[i]+j)+k) <<" ";
                //cout<< *(*(*(arr+i)+j)+k) <<" ";
                cout<< *(p+i*3*4+j*4+k) <<" ";
            cout<<endl;
        }
        cout<<endl;
    }

    int (*ap)[3][4] = arr; // 如果将三维数组理解为层、行、列,则ap为层指针,指向每层的首地址
    for(i=0;i<2;i++)
    {
        for(j=0;j<3;j++)
        {
            for(k=0;k<4;k++) // 以下两种方式等价
                //cout<< ap[i][j][k] <<" ";
                cout<< *(*(*(ap+i)+j)+k) <<" ";
            cout<<endl;
        }
        cout<<endl;
    }
    while(1);
    return 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
*/
C|二维、三维数组的多种遍历方法 (https://mushiming.com/) 技术博客 第2张

-End-

THE END

发表回复