数组指针、指针数组以及二位数组的深入解析

 更新时间:2013年09月04日 09:49:25   作者:  
下面来讲讲多维数组与指针的关系。与普通数组一样,使用多维数组时,实际上将其自动转换为指向该数组第一个元素的指针

int *p[3]与int (*p)[3]的区别
*p[3]这个是一个指针数组,它所代表的意思是数组中的每一个元素都是一个指针变量,而(*p)[3],p是一个指针变量,表示指向一个含有3个整型元素的一维数组。

复制代码 代码如下:

int i,j;
    int a[2][3]={3,4,5,6,7,8}; //
    int *p[3] ;  //表示一个数组,数组中的元素是指针类型,一共有三个元素
    int (*q)[3]; //是一个指针,指向一个含有三个int型的数组(q+1)会跳三个数组元素

    //把第一行三个元素地址存放在p指针数组中
    for( i=0;i<3;++i)
        p[i]=&a[0][i];

    //输出指针数组中地址所对应值
    for( j=0;j<3;++j)
        cout<< *p[j]<<" ";//输出结果为:3,4,5
    cout<<endl;

    q=a;//把数组a开始地址赋给指向一维数组q;
    for(i=0;i<2;i++)
        for(j=0;j<3;j++)
            cout<< *(*(q+i)+j)<<" "; //输出数组中元素

    system("pause");


参考《c++ primer》
严格的将,c++中没有多维数组,通常所指的多维数组其实就是数组的数组,比如int arry[3][4];表示一个长度为3的数组,数组中的每个元素是一个长度为4的数组。在使用多维数组时,记住这一点有利于理解其应用。

下面来讲讲多维数组与指针的关系。与普通数组一样,使用多维数组时,实际上将其自动转换为指向该数组第一个元素的指针。也就是说,数组的名字是一个指向该数组中第一个元素的指针,在一维数组中,arry==&arry[0],这两个地址是一样的。在二维数组中,数组名称指向第一个元素,第一个元素是一个长度为4的数组。我们定义一个指向长度为4的数组的指针 int (*p)[4],然后可以将二维数组的首地址赋值给它,p=arry。这样是可以进行赋值的。这里同样满足arry==&arry[0]。

知道了二维数组名字与指针的关系,那么我们在进行二维数组传参的时候就会好理解很多,以前二维数组传参是一直让人头疼的问题。这里我们还是将二维数组名字作为实参来传递,在接受函数的形参中,我们只需要定义一个指向具体长度为数组的指针即可,比如我们这里使用 int (*p)[4]来接受arry这样的参数。下面给出代码实例。

复制代码 代码如下:

#include<iostream>
#include<stdlib.h>
using namespace std;

//数组名字是一个指向数组首元素的指针,这里我们定义一个指向数组的指针来接受arry
//r表示二位数组的行数,c表示二维数组的列数。
void PrintArry(int (*arry)[4],int r,int c)
{
    for(int i=0;i<r;i++)
    {
        for(int j=0;j<c;j++)
        {
            cout<<arry[i][j]<<" ";
        }
        cout<<endl;
    }
}

void main()
{
    int arry[3][4]={{1,2,8,9},{2,4,9,12},{4,7,10,13}};
    PrintArry(arry,3,4);//等价于PrintArry(&arry[0],3,4);
    system("pause");
}


上述一个简单的打印二维数组的简单例子,重点是二维数组的传参。

更优化的方法
在上述示例中,形参必须指明这个arry指针是指向一个长度为多少的数组,如int (*arry)[4]必须指明为4,有一定的局限性,那么有没有更好的方法呢。答案是有的。考虑到二维数组在内存中占据连续的空间这一个特性,我们可以用以为数组来表达二位数组。将上述PrintArry方法进行改写,改写结果如下:

复制代码 代码如下:

#include<iostream>
#include<stdlib.h>
using namespace std;

//传入数组的指针,二维数组的行数与列数
void PrintArry2(int *arry,int r,int c)
{
    for(int i=0;i<r*c;i++)
    {
        cout<<arry[i]<<" ";
    }
    cout<<endl;
}

void main()
{
    int arry[4][4]={{1,2,8,9},{2,4,9,12},{4,7,10,13},{6,8,11,15}};
    PrintArry2(&arry[0][0],4,4);//传入数组中的第一个数组中的第一个元素的地址

    system("pause");
}

相关文章

  • C语言中的内存管理详情

    C语言中的内存管理详情

    这篇文章主要介绍了C语言中的内存管理详情,手工申请内存使用malloc展开全文内容,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • C++ Boost ProgramOptions超详细讲解

    C++ Boost ProgramOptions超详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言每日练习之进制转换

    C语言每日练习之进制转换

    这篇文章主要介绍了C语言进制转换,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-11-11
  • 详解如何将Spire.XLS for C++集成到C++程序中

    详解如何将Spire.XLS for C++集成到C++程序中

    Spire.XLS for C++ 是一个 Excel 库,供开发人员在任何类型的 C++ 应用程序中操作 Excel 文档(XLS、XLSX、XLSB 和 XLSM)。 本文演示了如何以两种不同的方式将 Spire.XLS for C++ 集成到您的 C++ 应用程序中
    2023-03-03
  • C++学习之函数模板的使用详解

    C++学习之函数模板的使用详解

    函数模板可以适用泛型来定义函数,其中泛型可以是(int, double, float)等替换。这篇文章主要来和大家聊聊函数模板的具体使用,感兴趣的可以了解一下
    2023-03-03
  • c++ std::invalid_argument应用

    c++ std::invalid_argument应用

    想研究std::invalid_argument的朋友可以参考下
    2013-01-01
  • 详解C++编程中类模板的相关使用知识

    详解C++编程中类模板的相关使用知识

    这篇文章主要介绍了详解C++编程中类模板的相关使用知识,包括函数的参数类型替换等方法,需要的朋友可以参考下
    2015-09-09
  • 基于c++中的默认拷贝函数的使用详解

    基于c++中的默认拷贝函数的使用详解

    本篇文章对c++中默认拷贝函数的使用进行了详细的分析介绍。需要的朋友参考下
    2013-05-05
  • C++深入探究重载重写覆盖的区别

    C++深入探究重载重写覆盖的区别

    C++ 允许多个函数拥有相同的名字,只要它们的参数列表不同就可以,这就是函数的重载(Function Overloading),借助重载,一个函数名可以有多种用途
    2022-08-08
  • C++ 分割字符串数据的实现方法

    C++ 分割字符串数据的实现方法

    这篇文章主要介绍了C++ 分割字符串数据的实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09

最新评论