二维“数组”转换成二维“指针”

今天写函数时遇到了一个问题,怎么返回二维数组?

想法:直接将返回值定义为二级指针,将二维数组与二级指针转化,想了想发现根本不可行。二级指针和二维数组并不等价。

查找了下资料,发现了论坛https://bbs.csdn.net/topics/360158391大家的讨论。

我们先看下二维数组与二级指针问题:cannot convert from 'double [10][10]' to 'double ** '
例如:

double arry[5][10] = {0};       
double** pp;
pp=arry;

           直接的赋值会提示错误:cannot convert from 'double [10][10]' to 'double ** '

解决方法:

double arry[5][10] = {0};       
double (*p)[5];
for(int i=0;i<5;i++)
     p[i]= arry[i];

          这样既可解决问题。一个函数形如:

void f(float **p){
/* 想要在函数体中按二维数组的方式访问*/
 p[1][1] = 0;//c++用vc编译ok,运行出错(非法访问)
}

float **p; //其实这里的p并不是一个二位数组的指针,只不过是一个指向指针的指针


像你这样访问肯定是会出问题的。

例如:

float a[2][2]={0,1,2,3};
float **p=(float**)a;//强制将二维数组指针转为指向指针的指针


则此时

p[0]=0;

p[1]=1;

p[2]=2;

p[3]=3;

p[0][0]=*(*(p+0)+0)=**p;

p[0][1]=*(*(p+0)+1);

对于p[0][0]:由于*p=0; ====> **p=*(0);引用地址为零的内存,必然是错误的。

对于p[0][1]=*(*p+1)====>*(4),引用了非法内存

同样,对于p[1][0]=*(1),p[1][1]=*(5),均引用了非法内存

所以说,二位数组并不能简单的转换成指向指针的指针。

正确的指向二维数组的指针应该是:

float a[5][10];

float (*p)[10];//只需要定义为指向第二维的指针,忽略第一维

p=a;

p[0][1]=a[0][1];

 

二级指针和二维数组并不等价。

二级指针是一个指向指针的指针 
而二维数组其实就是一个指针,char a[3][4]; a是指向整个二维数组的首地址。它相当于(char *)[n],并不是char **;

所以不能直接:t=a; 
要这样:t = (char **)a;

我们知道char array[]=”abcdef”; array是数组的首地址, 
那么在二维数组中array当然也是数组的首地址, 
看看这个定义char Array[][3] ={“ab“,“cd“,“ef“}; 
怎么知道的呢?定义这样一个数组,在vc调试窗口中 
我们看到: 

Array ---------0x64324234 

|------Array[0]---0x64324234 “ab“ 

|------Array[1]---0x64324337 “cd“ 

|------Array[2]---0x6432433A “ef” 

已经很明白了,实际编译器是这样实现二维数组的,实际上Array是“一维指针数组“的首地址,其中每一个元素指针都对应一个字符串,那么好我们来看看是否可以这样来使用Array二维数组。
char **pArray = Array;编译器提示出错,怎么办呢?加个(char **)试试,仍然出错。

设断看一下pArray的值和Array的值是相等的,但我们是否可以象使用Array那样来同样输出字符串呢?

很明显是不行的,编译器不会把pArray+i处理成pArray+i*3寻找到第i个指针的地址,而只是简单的加了一个i.这说明编译器只做了很简单的将地址值赋给了pArray,而它实际没有任何意义.我们不能用它来访问任何数据.很奇怪吗? 
再来看看这样定义char *p[] = {“ab“, “cd“, “ef“};定义了一个指针数组.char **sp = p;这样的用法经常看到,为什么这样就可以使用sp来访问字符串了呢,的确编译器在编译的时候识别出了sp是一个指向一维数组的指针的指针,那么我们就可以把它做为数组名来操纵整个数组了.

解决一:将二维数组定义为全局变量。

              全局变量尽量少用,做项目时,可能会导致其他问题。

解决二:由于数组是不可修改的左值,所以在C/C++中函数的返回值不能是数组,但可以返回一个指向二维数组首元素的指针。例如:


int (*fun(int(&)[3][3]))[3];
......
int main( void )
{
    .....
    int a[3][3] = ..........;
    int ( *p )[3] = fun( a );
    .....
    p[1][2] = 3;    //等效于a[1][2] = 3
    .....
    return 0;
}

int ( *fun( int( &a )[3][3] ) )[3]
{
    return a;
}

大神的解释是:

int ( *p )[3]你应该知道是什么吧?一个指向int[3]数组的指针,然后用fun( int( &a )[3][3] )代替p,由于fun是一个函数,于是代替p后,就是一个返回数组指针的函数,这个函数的参数是int[3][3]数组的引用。

解决三:定义一个结构体,存放二维数组的指针,行数和列数,getInfo分配这个结构,赋值,并返回此结构的指针。

typedef struct {
    int** pStart;
    int size1d;
    int size2d;
} MyResult;

具体下次再议。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值