关于数组指针和指向数组指针的指针及其new

49 篇文章 0 订阅
35 篇文章 0 订阅

今天在CSDN上看到了wp123456xt对我很久以前的一篇文章——方正面试的题-找出字符串最多的分解方法http://blog.csdn.net/shizhixin/article/details/4742687的评论,很高兴有人能够提出问题,正好今天有时间,所以回复了。


后来在wp123456xt的CSDN的博文上看到他的一篇求助文章——数组指针问题(求指教),http://blog.csdn.net/wp123456xt/article/details/7021496,也无人回答,闲来无事,就一一解释下吧,这些理解都属于一家之见,也许其中的一些理解上会有问题,还希望大家指出,共同进步嘛。


相关主程序和ex小例子代码可以在我的资源中下载:http://download.csdn.net/detail/shizhixin/3892608

#include<iostream>
using namespace std;
int main()
{
float(**q)[5];
float a[1][5]={{1,2,3,4,5}};
q=&new float [1][5];//编译可以通过
//q=&a;//编译通不过
//q=new float*;//此处我原本想先给q分配一个内存空间,用于存取二维数组a的地址
//却找不到合适的数据类型
*q=a;


for(int i=0;i<5;i++)
{
cout<<*(**q+i)<<endl;
printf("%p\n",**q+i);
}
cout<<endl;
cout<<&q<<endl;
 return 0;
}

/*
一一解析你的代码,你的代码用--标志的行


--float(**q)[5];
这里定义的q,是一个指向(数组指针)的指针,本质上它是一个二级指针,他的下一级是一个指向[5]大小的
数组的指针,最终才是一个二维的数组类型;如下图,如果真正理解了这个,基本上后面的就不难理解了;


--float a[1][5]={{1,2,3,4,5}};
a当然是一个1*5的二维数组;


--q=&new float [1][5];//编译可以通过
这句话可以拆分开来看,就比较容易理解为什么能编译通过了,拆分如下:
float (*b)[5] = new float[1][5]; //b是一个数组指针,指向了一个新开辟的数组,这个肯定没问题吧
q=&b; //用一个二级指针,就是指向(数组指针b)的指针即q,这样q这个指针里存储b的地址,这个当然是可以的啊。
如果还不理解的话看下面这段:
ex1:
int ** pa; //相当于q
int *pb;   //相当于b
int n=10;  //相当于a
pb=&n;     
pa=&pb;//这样没编译肯定没问题吧,并且**pa,*pb的值应该和n的值都相等吧。




--//q=&a;//编译通不过 
自然,上面那个例子,pa=&n,这样可以么??


-- //q=new float*;//此处我原本想先给q分配一个内存空间,用于存取二维数组a的地址
-- //却找不到合适的数据类型
如果只是仅仅为了暂时存储二维数组a的地址方便操作二维数组之用,没必要new一个内存空间,如上面的代码中
pa也没有去new一个空间来存储a的地址,程序会自动在编译系统就为已定义的变量分配相应的内存单元的。
退一步说,如果你一定要new,比如同时操作多个,那应该怎么new呢,还是上面那个例子,
int * pb = new int;
int ** pa = new int*;
应该这么new吧,也就是定义的这个pb指针,他指向new的存储区的数据类型是int型的,同样,pb指向的是int*的
数据类型,那new的话应该new int*;所以对于我们的float(**q)[5],q开始说了是指向(数组指针b)的指针,而
b的类型是float (*b)[5],所以应该这么new:float(**q)[5] = new (float(*)[5]);如果你想同时new n个这样
指向数组指针的指针,那就int(**q)[5]=new (int(*[n])[5]); 不过这里释放的时候要注意,和new二维数组一样,
要先delete [] p[0--n];然后再delete [] p;例如:
ex2:
int(**p)[2]=new (int(*[3])[2]); //注意new后面的括号
p[0]=new int[2][2]; 
p[1]=new int[2][2]; 
p[2]=new int[2][2]; 
delete [] p[0]; 
delete [] p[1]; 
delete [] p[2]; 
delete [] p;


int(**q)[2]=new (int(*)[2]); //一个的情形
delete []q;




 -- // *q=a;
编译上是可以通过的,毕竟相当于第一个例子中*pa=&n(*pa=pb,pb=&n),这里a也是代表其首地址,
但是需要注意的一个问题,直接把a的值赋予*q,*q所代表的是q所指向的内容,
而如果开始q指向哪里了都没定义,这样肯定编译没问题,但是程序运行有问题的。换句话说,如果程序如下:
ex3-1:
float(**q)[5];
float a[1][5]={{1,2,3,4,5}};
*q=a;//能编译但这样是有问题的!!

ex3-2:
float(**q)[5];
float a[1][5]={{1,2,3,4,5}};
q=&new float [1][5];
*q=a;//编译能通过,并且赋值也是正确的


-- for(int i=0;i<5;i++)
-- {
-- cout<<*(**q+i)<<endl;
-- printf("%p\n",**q+i);
-- }
-- cout<<endl;
-- cout<<&q<<endl;
这段代码应该不难理解,但是也需要注意的一个地方是
**q是获取a的首地址里面的内容,
**q+i是获取a的首地址然后偏移i个float单位,注意这里的偏移单位和数组指针直接+1不一样,这里是q
先获得首地址,然后偏移i个单位,通过下面这个例子慢慢体会:
ex4:
float a[2][5]={{1,2,3,4,5},{7,8,9,0,1}};
float (*b)[5];
b=a;
for (int i=0;i<2;i++)
{
cout<<**(b+i)<<endl; //output: 1,7
cout<<**b+i<<endl;   //output:1,2
}

 */

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值