(C/C++学习心得)6.数组指针和指针数组(祝大家国庆快乐!!)

发布日期:2019-01-28

说明:int (*p)[4] 和 int *p[4](数组指针和指针数组)如果你是一个初学者也许当你看到这两个名词的时候已经懵了。其实只要你理解了其中的含义.这两个名词对你来说会相当简单并且很有趣下面我们就来深入探讨一下究竟什么是数组指针什么是指针数组。

 

一.指针数组

1.前面我们已经学过数组了比如说要创建一个一维整型数组该怎么创建呢?应该是这样的:int arr[N]其中arr是数组名即变量名N是你所创建的这个数组中的元素个数而前面的int则是这些元素的类型。所以其实可以将它读作整型变量数组。那万一你所创建的数组元素不是整型和浮点型这些基本类型而是一个指针类型呢?这就是指针数组了。

2.指针数组首先它也是一个数组只不过这个数组中的元素的类型为指针类型举个例子:double *arr[4]这是一个指针数组包含四个元素其中每个元素都是double*类型的简单来说它就是一个用来存储指针的数组。用一个图来说明这个指针数组的内存布局:

3.既然指针数组是一个数组那么它就应该有数组所应具有的一些特点。举个例子对于double* p[4]p+1加的是数组的步长即一个double*的大小四个字节(注意:在32位机中所有指针的大小都为4个字节)。而如果对数组名p进行取地址后则&p+1加的是sizeof(p)即4*4 = 16个字节即&p+1就跨过了整个数组。

示例:

1 #include<stdio.h> 2 int main() 3 { 4 double *p[4] = {NULL} 5 printf("p = %p"p) 6 printf("p+1 = %p"p+1) 7 printf("&p = %p"&p) 8 printf("&p+1 = %p"&p+1) 9 return 0 10 }

程序运行结果:

 

 

二.数组指针

1.指针相信大家都比较熟悉了比如:int *p定义了一个指针p该指针指向一个整型数据单元如果对该指针执行加1操作则加的是4个字节又如char *q定义了一个指针q该指针指向一个字符型的数据单元如果对该指针执行加1操作则实际上加的是1(个字节)。那么问题来了万一要定义一个指针它所指向的数据单元为一个一维数组怎么办呢?对他执行加1操作又能得到什么呢?这就是数组指针了。

2.数组指针首先得明白它是一个指针只不过这个指针指向的数据单元为一个数组举个例子现在有一个一维数组int arr[4]现在要定义一个数组指针来指向它按照一般指针的理解应该是这样的int[4]* p表示定义一个指针p而该指针的类型为int[4]*型的但这在编译器中是会报错的没什么理由语法规定。实际上对这个数组指针的定义应该是这样的:int (*p)[4] = arr说实话这样看着笔者觉得挺别扭的不过没办法编译器就只认这个写法不过这完全不影响我们按照第一种写法去理解数组指针的本质。

3.上面已经说了数组指针实质就是一个指针只不过其指向的类型与基本类型不同罢了。对于基本类型的指针执行加1加的是指针指向数据类型的字节数那么对于数组指针呢?显然加1加的也是指针指向数据类型的字节数那么数组指针指向数据类型的大小怎么判断呢?举个例子:int(*p)[4]下面将通过一张内存数据图对此进行阐述:

如图:该指针里面存的是一个数组的首地址只不过该指针的类型为int[4] *型这就导致了该指针的步长为4*4 = 16个字节所以对该指针执行加一操作实际上加的是16个字节即整个数组的大小。

1 #include<stdio.h> 2 int main() 3 { 4 int arr[4] 5 int (*p)[4] = (int(*)[4])arr 6 printf("%p"p) 7 printf("%p"p+1) 8 return 0 9 }

程序运行结果:

4.数组指针与二维数组的关系是什么呢?首先要知道二维数组 int arr[m][n] 可以想象成是具有m行n列的一个数组矩阵也可以想象成是有m个一维数组其中每个一维数组里面又有n个int型的元素.那么是否可以用一个类型为int[n] *型的指针指向该二维数组来实现行间跳转访问呢?答案是肯定的!就拿上面例子来说假如有一个二维数组int arr[m][n]则可以定义一个数组指针为:int (*p)[n] = arr(这里最好强转一下)然后用p对数组进行访问由以上可讲可知这里的p+1加的是n*4个字节即加的是二维数组每行的字节数。

示例:

1 #include<stdio.h> 2 int main() 3 { 4 int arr[3][4] 5 int (*p)[4] = (int(*)[4])arr 6 printf("%p"p) 7 printf("%p"p+1) 8 return 0 9 } 10

程序运行结果:

注意:二维数组的存储在内存中实际上是线性存储的可以说任何数据在内存上的存储都是线性存储的但这并不影响我们用二维的思维去理解它。

 

三.下面是一个数组指针当做二维数组名访问数组的示例只是为了巩固与拓展一下以上对于二维数组名的具体使用方式在下次更新(后天)会详细介绍。这里就简单介绍一下当把二维数组名赋给一个指针数组后例如如下示例则该指针就拥有了二维数组名访问二维数组的方式比如在这里p代表数组的首地址由于其拥有了二维数组名的特性则**p就是二维数组里的第一个元素而*(*(p+i)+j)是二维数组第i行第j列的元素。

示例:

1 #include<stdio.h> 2 int main() 3 { 4 int arr[3][4] 5 int count = 0 6 for(int i = 0i<3i++) 7 for(int j = 0j<4j++) 8 arr[i][j] = count++ 9 for(int i = 0i<3i++) 10 { 11 for(int j = 0j<4j++) 12 printf("%2d "arr[i][j]) 13 putchar(10) 14 } 15 int (*p)[4] = (int(*)[4])arr 16 for(int i = 0i<3i++) 17 { 18 for(int j = 0j<4j++) 19 printf("%2d "*(*(p+i)+j)) 20 putchar(10) 21 } 22 return 0 23 }

程序运行结果: