说明: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就跨过了整个数组。

示例:

 #include<stdio.h>
int main()
{
double *p[4] = {NULL};
printf("p = %p\t",p);
printf("p+1 = %p\n",p+1);
printf("&p = %p\t",&p);
printf("&p+1 = %p\n",&p+1);
return 0;
}

程序运行结果:

二.数组指针

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个字节,即整个数组的大小。

 #include<stdio.h>
int main()
{
int arr[4];
int (*p)[4] = (int(*)[4])arr;
printf("%p\t",p);
printf("%p\n",p+1);
return 0;
}

程序运行结果:

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个字节,即加的是二维数组每行的字节数。

示例:

 #include<stdio.h>
int main()
{
int arr[3][4];
int (*p)[4] = (int(*)[4])arr;
printf("%p\t",p);
printf("%p\n",p+1);
return 0;
}

程序运行结果:

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

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

示例:

 #include<stdio.h>
int main()
{
int arr[3][4];
int count = 0;
for(int i = 0;i<3;i++)
for(int j = 0;j<4;j++)
arr[i][j] = count++;
for(int i = 0;i<3;i++)
{
for(int j = 0;j<4;j++)
printf("%2d ",arr[i][j]);
putchar(10);
}
int (*p)[4] = (int(*)[4])arr;
for(int i = 0;i<3;i++)
{
for(int j = 0;j<4;j++)
printf("%2d ",*(*(p+i)+j));
putchar(10);
}
return 0;
}

程序运行结果:

(C/C++学习)6.数组指针和指针数组的更多相关文章

  1. C语言学习笔记(一):数组传递时退化为指针

    这几天闲来无事,写了一个数组元素排序函数如下: #include <stdio.h> #include <stdlib.h> void ArraySort(int array[ ...

  2. C语言学习笔记--数组参数和指针参数

    1. 数组参数退化为指针的意义 (1)C 语言中只会以值拷贝的方式传递参数,当向函数传递数组时,将整个数组拷贝一份传入函数导致执行效率低下,C 语言以高效作是最初的设计目标,所以这种方法是不可取的. ...

  3. C语言学习笔记--数组指针和指针数组

    C 语言中的数组有自己特定的类型,数组的类型由元素类型和数组大小共同决定.(如 int array[5]类型为 int[5]) 1.定义数组类型 C 语言中通过 typedef 为数组类型重命名:ty ...

  4. C学习笔记(3)---作用域,数组, (少量指针入门)

    1. 作用域(scope):任何一种编程中,作用域是程序中定义的变量所存在的区域,超过该区域变量就不能被访问.C 语言中有三个地方可以声明变量. a. 在函数或块内部的局部变量 - 在某个函数或块的内 ...

  5. iOS 阶段学习第八天笔记(指针)

    iOS学习(C语言)知识点整理 一.指针 1)概念:存储变量的地址的一个变量. 2) 数据存储类型分析 1.text (代码段) :存储二进制的可执行代码 2.data(初始化的数据段) 存储初始化的 ...

  6. iOS学习07之C语言指针

    本次随笔主要是为了学习和理解C语言中的指针,指针树状图如下: 1.访问数据的两种方式 1> 直接访问:定义变量后,直接访问变量 ; printf("a = %d\n", a) ...

  7. C语言笔记(二维数组与数值指针)

    一.关于二维数组和二维数组区别 (1)一维数组在内存中是连续分布存储的,同样,二维数组也是在内存连续存储的.所以从内存的角度来分析,一维数组和二维数组其实没有本质区别. (2) 二维数组可以使用一维数 ...

  8. c/c++ 数组的智能指针 使用

    数组的智能指针 使用 数组的智能指针的限制: 1,unique_ptr的数组智能指针,没有*和->操作,但支持下标操作[] 2,shared_ptr的数组智能指针,有*和->操作,但不支持 ...

  9. C语言复习---二维数组和二级指针的关系:没关系,别瞎想(重点)

    前提:一维数组和一维指针为什么可以替换使用? ] = { , , }; int *p = a; ; i < ; i++) printf("%d ", *(p + i)); 上 ...

随机推荐

  1. js将图片转为base64编码,以字符串传到后台存入数据库

    (前台在中approve_edit.html中,后台不变) 链接参考:http://www.cnblogs.com/Strom-HYL/p/6782176.html 该链接文中并没有用到easyUI的 ...

  2. 51nod 1611 金牌赛事

    被亮亮D飞啦!!QWQ 这题明明是最大权闭合子图+线段树优化构图好不好 被迫考虑DP,并且考虑f[i]表示到第i个位置的最大值(第i个位置可选可不选) 对于最终的答案,我们可以分割成一段一段的,也就是 ...

  3. java dom4j 读写XML

    <?xml version="1.0" encoding="UTF-8"?> <Configuration> <Config id ...

  4. java异步编程

    异步编程提供了一个非阻塞事件驱动的模型.通过异步消除阻塞,可以让web服务响应更多请求.可以让系统更高效的执行.比如log框架,记录日志或异常时异步执行可避免影响正常业务流程的执行. 异步变成如何把线 ...

  5. D. Toy Sum(cf)

    http://codeforces.com/problemset/problem/405/D 题意:已知集合S={1,2,3......1000000},s=1000000,从集合S中选择n个数,X= ...

  6. codevs1036商务旅行(LCA)

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 某首都城市的商人要经常到各城镇去做 ...

  7. [App Store Connect帮助]一、 App Store Connect 使用入门(2)登录至 App Store Connect

    请使用您的 Apple ID 登录 App Store Connect.如果您是具有“帐户持有人”职能的用户,请使用您用于加入“Apple 开发者计划”的 Apple ID 登录并添加其他用户至您的 ...

  8. sql 查询出当天记录数据

    select updatetime,NewComment,HistoryID,sum(1) over(partition by UpdateTime) from LPProjectHistoryord ...

  9. 各地图API坐标系统比较

    各地图API坐标系统比较 简单记录一下各家坐标系 WGS84坐标系:即地球坐标系,国际上通用的坐标系.设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,谷歌地图采用的是WGS84地 ...

  10. ORACLE SEQUENCE用法(转)

    ORACLE SEQUENCE用法 在oracle中sequence就是序号,每次取的时候它会自动增加.sequence与表没有关系. 1.Create Sequence     首先要有CREATE ...