C++动态数组,多重指针问题
来源:互联网 发布:阿里云华北3是什么地方 编辑:程序博客网 时间:2024/05/16 18:28
今天遇到一个问题,要开辟一个二维指针空间,详细的看了一下网上有关动态指针、动态数组等开辟方法以及学习前辈们对于动态数组问题的解决经验!
一、
首先说明一下多重指针问题,这里解释到第三层,为了方便理解,我们可以将三重指针理解为三维数组,
首先看一个经典的例子:
int ***a,x=10,y=20;
a=(int ***)malloc(sizeof(int)*x);//分配是什么?
for(i=1;i<10;i++){
(*a)[i]=(int *)malloc(sizeof(int)*y);//分配的又是什么?
}
for(i=1;i<x;i++)
for(j=1;j<y;j++)
{
(*a)[i][j]=10;//这样赋值对不
}
1: *a=(int **)malloc(sizeof(int)*x);可以理解为二重指针的第一层,分配了10个int型的二重指针空间
a是三重指针的地址,*a是二重指针的首地址;(*a)[0];(*a)[1];(*a)[2];(*a)[3];(*a)[4]........
2: (*a)[i]=(int *)malloc(sizeof(int)*y);这个代表每一个二层指针又被分配了空间;这里每一二层指针被分配了
20个(int *)的指针;即,每一二层指针又有20个孩子
3: (*a)[i][j]=10;这样赋值正确,前边的(*a)是获取一个二维数组,后边是一个二维数组的一个元素。直接赋值是可以的
4: 我们同样可以理解为树形,几重指针就是几层树
以上是关于三维指针的解释,二维指针也就是可以理解成二维数组。
二、数组的指针、指针数组以及指向指针的指针
考虑数组的指针的时候我们要同时考虑类型和维数这两个属性。换一句话,就是说一个数组排除在其中存储的数值,那么可以用类型和维数来位置表示他的种类。
A)一维数组
在c和c++中数组的指针就是数组的起始地址(也就第一个元素的地址),而且标准文档规定数组名代表数组的地址(这是地址数值层面的数组表示)。例如:
int a[10]; int *p;
p=&a[0]//和p=a是等价的:
因为a是数组名,所以他是该数组的地址,同时因为第一个元素为a[0],那么&a[0]也代表了该数组的地址。但是我们是不是就说一个数组名和该数组的第一个元素的&运算是一回事呢?在一维的时候当时是的,但是在高维的时候,我们要考虑到维数给数组带来的影响。
a[10]是一个数组,a是数组名,它是一个包含10个int类型的数组类型,不是一般的指针变量噢!(虽然标准文档规定在c++中从int[]到int*直接转换是可以的,在使用的时候似乎在函数的参数为指针的时候,我们将该数组名赋值没有任何异样),a代表数组的首地址,在数字层面和a[10]的地址一样。这样我们就可以使用指针变量以及a来操作这个数组了。
所以我们要注意以下问题:
(1) p[i]和a[i]都是代表该数组的第i+1个元素;
(2) p+i和a+i代表了第i+1个元素的地址,所以我们也可以使用 *(p+I)和*(a+I)来引用对象元素;
(3)p+1不是对于指针数量上加一,而是表示从当前的位置跳过当前指针指向类型长度的空间,对于win32的int为4byte;
B)多维数组
对于二维数组a[4][6];由于数组名代表数组的起始地址,所以a(第一层)和第一个元素a[0][0]地址的数字是相同的,但是意义却是不同的。对于该数组我们可以理解为:a的一维数组(第一层),它有四个元素a[0]、a[1]、a[2]、a[3](第二层),而每个元素又含有6个元素a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三层),…到此我们终于访问到了每个元素了,这个过程我们经历了:a->a[0]->a[0][0];
整体来讲:a是一个4行5列的二维数组,a表示它指向的数组的首地址(第一个元素地址&a[0]),同时a[0]指向一行,它是这个行的名字(和该行的第一个元素的首地址相同(第一个元素为地址&a[0][0]))。所以从数字角度说:a、a[0]、&a[0][0]是相同的,但是他们所处的层次是不同的。
既然a代表二维数组,那么a+i就表示它的第i+1个元素*(a+i)的地址,而在二维数组中
*(a+i)又指向一个数组,*(a+i)+j表示这个数组的第j+1个元素的地址,所以要访问这个元素可以使用 *(*(a+i)+j)(也就是a[i][j])。
他们的示意图为(虚线代表不是实际存在的):
对照这个图,如下的一些说法都是正确的(对于a[4][6]):
a是一个数组类型,*a指向一个数组;a+i指向一个数组;a、*a和&a[0][0]数值相同;a[i]+j和*(a+i)+j是同一个概念; 总结一下就是:我们对于二维指针a,他指向数组a[0,1,2,3],使用*,可以使他降级到第二层次,这样*a就指向了第一个真正的数组。对于其他的情况我们也可以采用相同的方式,对于其他维数和类型的数组我们可以采用相类似的思想。
说到指向数组的指针,我们还可以声明一个指针变量让它指向一个数组。例如:
int (*p)[5];
这时p就是一个指针,要指向一个含有5个int类型元素的数组,指向其他的就会出现问题。
这个时候我们可以使用上面的什么东西来初始化呢?
我们可以使用*a,*(a+1),a[2]等。
原因很简单:我们在一个二维的数组中,那么表达方式有上面的相互类似的意义呢?只有 *a,*(a+1),a[2]等,
C)指针数组
一个指针数组是指一个数组中的每个元素都是一个指针,例如:
int *p[10];//而不能是int (*p)[10]
或者
char *p[10];
此时p是一个指针(数值上和&p[0]一样);
在前面有int t[10];
int * pt=t;//使用pt指向t
那么这里我们用什么指向int *t[10]中的t呢?我们要使用一个指针的指针:
int **pt=t;
这是因为:在int *t[10]中,每个元素是指针,那么同时t又指向这个数组,数组上和&t[0]相同,也就是指向t[0],指向一个指针变量,可以说是一个指针的指针了,所以自然要用
int **pt;
D)指针的指针
一个指针变量内部可以存储一个值,这个值是另外一个对象的地址,所以我们说一个指针变量可以指向一个普通变量,同样这个指针变量也有一个地址,也就是说有一个东西可以指向这个指针变量,然后再通过这个指针变量指向这个对象。那么如何来指向这个指针变量呢?由于指针变量本身已经是一个指针了(右值),那么我们这里就不能用一般的指针了,需要在指针上体现出来这些特点,我们需要定义指针的指针(二重指针)。
int *p1=&i; int**p2=&p1;
综合以上的所有点,下面是我们常常看到一些匹配(也是经常出错的地方):
int a[3],b[2][3],c,*d[3]; void fun1(int *p); void fun2(int (*p)[3]); void fun3(int **p); void fun4(int p[3]); void fun5(int p[]); void fun6(int p[2][3]); void fun7(int (&p)[3]);
函数 不会产生编译时刻的可能值(但逻辑上不一定都对)
函数
不会产生编译时刻的可能值(但逻辑上不一定都对)
fun1
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun2
b,b+i,
fun3
d
fun4
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun5
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun6
b
fun7
a
此段文章出处:http://apps.hi.baidu.com/share/detail/38102294
三、
对于动态数组问题:
参阅他人的建议得知:使用一维数组实现多为数组的功能。定义动态啊的一维数组比较简单,而且所派分的内存单元都是连续的,其实在内存中的存储都是在一块连续的内存块上存储,性质一样!所以建议使用一维数组实现多维的功能;
实例如下:
1、用一重指针
int i,j,num1,num2;
int *p=new int[num1*num2];
for(i=0;i<num1;i++)
{
for(j=0;j<num2;j++)
{
p[i*num1+j]=i*j+5;//给数组赋值,调用的时候也是如此。
}
2、用二重指针
int num1,num2;
int **p;
p=new int*[num1];//开辟空间,理解起来有点难
for(int i=0;i<num1;i++)
p[i]=new int[num2];
另外两个实例:
一维动态数组的实例:
二维动态数组的实例:- C++动态数组,多重指针问题
- C++动态数组,多重指针问题
- 指针数组和多重指针
- C语言数组指针问题
- 多重循环和动态规划解决最大子数组问题
- C++:在多重继承时的指针转换问题
- C语言复习 -- 多重指针
- C语言 复杂指针的申明问题 数组指针 指针数组 函数指针 指针函数
- C语言数组,指针,函数等问题
- c语言数组指针的问题
- C语言二维数组中的指针问题
- C语言数组与指针的问题
- C数组和指针相关的问题
- c语言的数组与指针问题
- C/C++指针数组的问题
- 数组与指针--多维数组与多重指针使用注意事项
- 用多重数组来表示指针
- C语言回顾(七、多重指针,argc,argv,动态内存分配,void指针,const)——iOS开发基础
- 逆向生成模型工具
- 用PHP将CMYK格式的JPG文件转为RGB格式
- 思科第二本教材 第二章 静态路由 个人总结
- 添加自定义视图到导航条的标题栏
- android layer-list
- C++动态数组,多重指针问题
- 信息采集系统开发第一版
- Sql Server 游标的简单使用
- 计算机经典书籍(转载)
- Linux下执行ifconfig遇到错误: bash:ifconfig:command not found
- malloc与free 动态内存的申请与释放
- Linux Shell脚本实现自动交互
- Activity:前台+带UI的屏幕 Service:后台+不带UI BroadcastReceiver:不带UI
- 数据库游标