深入浅出C指针(三)多维数组

原创 2012年03月23日 10:26:05





1.概念
如果某个数组的维数不止1个,它就被称为多维数组。例如,下面这个声明:
int matrix[6][10];
创建了一个包含60个元素的矩阵。但是,它是6行每行10个元素,还是10行每行6个元素?
为了回答这个问题,你需要从一个不同的观点视察多维数组。考虑下列这些维数不断增加的声明:
int a;
int b[10];
int c[6][10];
int d[3][6][10];
a和b很好理解。c只是在b的基础上在增加一维,所以我们把c看作是一个包含6个元素的向量,只不过他的每个元素本身又是一个包含10个元素的向量。换句话说,c是一个一维数组的一维数组。d也是如此:它本身是一个含有3个元素的向量,而这三个元素中每个元素本身又是一个含有6个元素的向量,而这6个元素各自本身又是一个含有10个元素的向量。 


2.存储顺序
请记住,多维数组只是表示上的一种写法,而在实际的内存空间存储中,还是按照顺序的存储方式。
例如:int[2][5];
在内存中是按顺序排列的10个小区域。
看看下面这个例子:
int matrix[6][10];
int *mp;
.....
mp = &matrix[3][8]
printf("First value is %d\n",*mp);
printf("Second value is %d\n",*++mp);
printf("Third value is %d\n",*++mp);
很显然,第一个被打印的值将是matrix[3][8]的内容,那下一个被打印的又是什么?顺序存储可以回答这个问题--下一个元素将是最右边下标首先变化的那个,也就是matrix[3][9]。再接下去又轮到谁呢?第9列已是最后一列。不过,按顺序存储的规定,一行存满后就轮到下一行,所以下一个被打印的元素将是matrix[4][0]。


2.数组名
一维数组的数组名是一个指针常量,这一点大家应该已经十分清楚了。它的类型是“指向元素类型的指针”,它指向数组元素的第一个元素。多维数组也差不多,但是这个“差不多”往往会给初学者带来一定的误导,多维数组的数组名,也是一个指针,这个指针指向的是该数组的第一个“元素”,这个“元素”也是一个数组。例如,下面这个声明:
int matrix[3][10];
接着看以下的表达式:
matrix[1][5]
这个很简单,该表达式表示这个数组的第二行,第六列所包含的元素。
matrix + 1
如果你认为这个表达式指向了第一行的第二个元素,那么你就错了。实际上,这个表达式指向的是第二行整个数组,而不是任何一个元素。
而*(matrix + 1)是一个指向第二行第一个元素的指针。*(*(matrix + 1))表示了第二行第一个元素的具体值。
其实就笔者感觉,C语言多维数组这样的设计方式不是十分恰当,这样做和一维数组的规则没有十分紧密的联系起来,就易于理解而言,matrix + 1表示第一行的第二个元素更为容易理解一些。不过可能是出于编码的简洁性考虑,C语言的发明人采用了这样“自动换行”的处理过程。
小提示:
在许多其他的语言,比如大家熟悉的C#中,多重下标被写成用逗号分割的形式。比如:
matrix[3,4];
如果你在C语言中这样写会发生什么呢?你的第一感觉一定是:编译错误。不过很可惜,C语言可以让这样的表达式编译通过(还记得2[array]吗?C语言的灵活性是其他语言所不能比拟的)。
这样看上去没有什么问题,实际这样的表达式运行结果一定会和你预想的结果不一样。
C语言的逗号表达式会将其转换成matrix[3]。
如果编译器可以发现这个错误还好,可惜由于逗号表达式的存在,编译器无法发现这样的错误。
3.指向数组的指针
下面这些声明合法吗?
int  vector[10], *vp = vector;
int  matrix[3][10], *mp = matrix;
第一个声明是合法的。它为一个整形数组分配内存,并把vp声明成一个指向整形的指针,并把它初始化指向vector数组的第一个元素。
第二个声明是非法的。它正确的创建了matrix数组,并把mp声明为一个指向整形的指针。但是,mp的初始化是不正确的,因为matrix并不是一个指向整形的指针,而是一个指向整形数组的指针。我们应该怎样声明一个指向整形数组的指针呢?
int (*p)[10];
这个声明略微复杂但却是正确的,在声明中加上初始化后是下面这个样子:
int  (*p)[10] = matrix;
它使p指向matrix的第一行。
p是一个指向拥有10个整形元素的数组指针。当你把p与一个整数相加时,该整数首先根据10个整形的长度进行调整,然后再进行加法。所以我们可以使用这个指针一行一行地在matrix中移动。
如果你需要的是一个指针逐个访问整形元素而不是逐行在数组中移动,我们可以这样声明:
int *pi = &matrix[0][0];
int *pi = matrxi[0];


4.初始化
对多维数组的初始化,一般有两种方式:
int matrix[2][3] = {100,101,102,103,104,105};
int matrix[2][3] = {
           {100,101,102},
           {103,104,105}
         };
二者在本质上没有任何区别,只是第二种初始化的方式程序可读性更高一些。
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

多维数组 和 多维指针

多维数组 和 多维指针

多维数组和指针

声明:1. 文章如有不妥的地方,请您指正,谢谢.          2.另外文中有些细节可能引用您的内容却未给出参考,请原谅我的疏忽,你的共享我不会忘记.    ...

指针数组 和 数组指针分析 main函数的参数

指针数组 和 数组指针分析 main函数的参数

用指针访问多维数组中的元素

指针访问多维数组中的元素char daytab[][12]={ {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31...
  • wy_ei
  • wy_ei
  • 2015-02-09 19:30
  • 820

二维数组和指针

二维数组和指针⑴ 用指针表示二维数组元素。要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整...
  • iu_81
  • iu_81
  • 2007-09-12 19:45
  • 47159

三维数组和三维数组的指针

本文主要给出三维数组和三维数组的指针的使用方法,对于二维数组和二维数组的指针的使用请参见: http://apps.hi.baidu.com/share/detail/6320035 在讲述之前,...

C/C++中二维数组和指针关系分析

在C/c++中,数组和指针有着密切的关系,有很多地方说数组就是指针式错误的一种说法。这两者是不同的数据结构。其实,在C/c++中没有所谓的二维数组,书面表达就是数组的数组。我猜想是为了表述方便才叫它二...

指针和数组(一维,二维,三维)以及野指针的避免

如何避免野指针? 答:①当指针未指向时,一般将指针置为空 ②当想向指针指向空间赋值时,为其分配空间。当用malloc为其分配空间的时候,要看其是否分配成功(注意清空原来的缓冲区),函数执行完以后,...

一维数组,二维数组,三维数组,数组与指针,结构体数组,通过改变指针类型改变访问数组的方式

 打印数组中的每个元素,打印每个元素的地址: #include #include   void main(void) {    ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)