c++高级---C/C++二维数组---与指针的关系

先上实例:

#include "stdafx.h"
#include <iostream>

int _tmain(int argc, _TCHAR* argv[])
{
 int v[2][10] = {{1,2,3,4,5,6,7,8,9,10},{11,12,13,14,15,16,17,18,19,20}};
 int (*a)[10] = v; //数组指针
 std::cout<<a<<std::endl;
 std::cout<<*a<<std::endl;
 std::cout<<**a<<std::endl;
 std::cout<<a[0]<<std::endl;
 std::cout<<std::endl;

//-------------------------------------------------------
 std::cout<<a+1<<std::endl;
 std::cout<<*(a+1)<<std::endl;
 std::cout<<**(a+1)<<std::endl;
 std::cout<<std::endl;

//-------------------------------------------------------
 std::cout<<(*a+1)<<std::endl;
 std::cout<<*(*a+1)<<std::endl;
 std::cout<<std::endl;

//-------------------------------------------------------
 std::cout<<(a[0]+1)<<std::endl;
 std::cout<<*(a[0]+1)<<std::endl;
 std::cout<<*(a[1])<<std::endl;
 //std::cout<<**(a[1])<<std::endl;
 return 0;
}

运行结果:

 

下面是收集的一些二维数组和指针的知识

参考:http://blog.csdn.net/yangchang999/article/details/6664069

很多C++/C初学者对于二维数组与指针的关系总是搞不清楚,对它的误解比比皆是。一下是本人的一些总结,部分内容参考相关资料,希望对大家的理解有所帮助。(本文对于C/C++而言)

首先,我们先从存储的角度对二维数组作一个全面的了解。二维数组在内存中的存储,是按照先行后列依次存放的。从内存的角度看,可以这样说,二维数组其实就是一个一维数组,在内存中没有二维的概念。如果把二维数组的每一行看成一个整体,即看成一个数组中的一个元素,那么整个二维数组就是一个一维数组,它以每一行作为它的元素,这个应该很好理解。

第一,我们来详细介绍二维数组与指针的关系。

首先定义个二维数组 array[3][4],p 为指向数组的指针。

若p=array[0],此时p指向的是二维数组第一行的首地址,则p+i将指向array[0]数组中的元素array[0][i]。由以上所介绍的二维数组在内存中的存储方式可知,对数组中的任一元素array[i][j],其指针的形式为:p+i*N+j(N为每一行的长度)。元素相应的指针表示法为:*(p+i*N+j),下标表示法为:p[i*N+j] 。

For Example:

array[4][3]={{1,2,3},{4,5,6},{7,8,9},{10,11,12}};

int * p=array[0];

数组array有四个元素,分别为array[0],array[1],array[2],array[3],每个元素为包含3个元素的一维数组,

如array[0]的3个元素为 array[0][0],array[0][1],array[0][2]。

元素array[2][2]对应指针为:array+2*3+2,

指针表示法为:*(array+2*3+2) , 

下标表示法为:array[2*3+2] 。

特别注意:虽然array[0]与array都是数组首地址,但两者指向的对象不同,这点要非常明确。array[0] 是一维数组的名字,它指向的是一维数组array[0]的首地址,所以 *array[0]与array[0][0]为同个值。而 array 是二维数组的名字,它指向的是所属元素的首地址,其每个元素为一个行数组。它是以‘行’来作为指针移动单位的,如array+i 指向的是第 i 行。对 array 进行 * 运算,得到的是一维数组 array[0] 的首地址,所以 *array 与 array[0] 为同个值。如果定义 int* p,p为指int类型的指针,指向int 类型,而不是地址。故以下操作 :p=array[0] (正确) ,p=array (错误) 。这点要非常注意。

【经测试输出array、array[0]与输出*array都是同一个值,都是整个二维数组第一个元素地址值,虽然变量array和array[0]以及*array的值一样,但他们的类型不一样,array指向一个大类型(大内存块),而array[0]和*array指向大类型内部的一个小类型(小内存块)。array[0]和*array这两个东西是一模一样的,值和类型都一样。】

【另外要注意也是需要死记硬背的东西是,array虽然指向一个大内存块的首地址(数组的首地址),但*array和array[0]的结果并不是返回整个大内存块内存放的内容(大数组),比如并不返回整个3个int元素,而是返回大内存块内部的小内存块的首地址(其实就是返回一个小数组),也即是只需要记住array是一种大类型的地址,而*array和array[0]仍然是一个地址,只不过类型是小类型而已,仅仅只是类型变了而已,值是不变的,至于为什么估计是编译器特殊实现了吧。】。

 

第二,看看如何用数组名作地址表示其中元素。

我们知道,对二维数组array,array[0]由array指向,故*array 与array[0] 是相同的,依次类推可得 array[i] 由array+i 指向,*(array+i) 与array[i]是相同的。 因此,对于数组元素 array[i][j] ,用数组名表示为 *(*(array+i)+j) ,指向该元素的指针为 *(array+i)+j 。

注意:数组名虽然是地址,但与指向数组的指针性质不同。指针变量可以随时改变其所指向对象,而数组名不可以,一旦被定义,就不能通过赋值使其指向另外一个数组,但是在Java中则可以。

 

第三,顺便了解一下不太常用的‘行数组指针’。

我们知道,对于二维数组array[4][3],与int* p 。二维数组名array 不能直接赋值给p。原因前面已讲过,两只的对象性质不同【类型不同】。在C语言中,我们可以通过定义一个行数组指针,使得这个指针与二维数组名具有同样的性质,实现它们之间可以直接赋值。行数组指针定义如下:

int (*p)[3]; 它表示,数组 *p 具有三个int类型元素,分别为 (*p)[0] , (*p)[1] , (*p)[2] ,即 p指向的是具有三个int类型的一维数组,也就是说,p为行指针。此时,以下运算 p=array 是正确的。

【int (*p)[3]中的小括号作用只是为了改变优先级,不加括号由于中括号优先级高于*号就变成了int* p[3],即一个一纬数组,每个元素都是int*类型的。】

【可以向c#那样把int (*p)[3]改成int[3] *p就好理解了。】

第四,二维数组作为函数参数。

二维数组作为函数参数一般有两种方式:(1) void func(int **array){...}   (2) void func(int array[ ][N])

注意第二种方式一定要指明二维数组的列数

当二维数组名作为函数实参时,对应的形参必须是一个行指针变量。

和一维数组一样,数组名传送给变量的是一个地址值,因此,对应的形参也必须是一个类型相同的指针变量,在函数中引用的将是主函数中的数组元素,系统只为形参开辟一个存放地址的存储单元,而不可能在调用函数时为形参开辟一系列存放数组的存储单元。

int main()

       double a[3][4];

       ……

       fun(a);

       ……

fun(double (*a)[n])

       ……

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值