您的位置:首页 > 编程语言 > C语言/C++

C语言中的二级指针和二维数组问题

2016-11-09 22:31 309 查看

C语言中的二级指针和二维数组问题

[日期:2015-03-16]来源:Linux社区  作者:fresh七天[字体:大 中 小]
<iframe id="iframeu2726899_0" src="http://pos.baidu.com/nctm?rdid=2726899&dc=2&di=u2726899&dri=0&dis=0&dai=1&ps=271x156&dcb=BAIDU_SSP_define&dtm=HTML_POST&dvi=0.0&dci=-1&dpt=none&tsr=0&tpr=1478700882440&ti=C%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E4%BA%8C%E7%BA%A7%E6%8C%87%E9%92%88%E5%92%8C%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E9%97%AE%E9%A2%98_Linux%E7%BC%96%E7%A8%8B_Linux%E5%85%AC%E7%A4%BE-Linux%E7%B3%BB%E7%BB%9F%E9%97%A8%E6%88%B7%E7%BD%91%E7%AB%99&ari=2&dbv=2&drs=1&pcs=1364x638&pss=1364x299&cfv=0&cpl=5&chi=1&cce=true&cec=UTF-8&tlm=1471836992&rw=638&ltu=http%3A%2F%2Fwww.linuxidc.com%2FLinux%2F2015-03%2F115055.htm&ltr=https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3DSKIr7Kl7iRk_EVogMuzAajdTOfS_0C7l0N8Mg08DNpfXyY7JpYdkJcd4S0wKdr7rBek8zcATesuRqZp1rEobCK%26wd%3D%26eqid%3D899dae770002822a0000000258232ee0&ecd=1&psr=1366x768&par=1366x728&pis=-1x-1&ccd=24&cja=false&cmi=7&col=zh-CN&cdo=-1&tcn=1478700882&qn=c9d499960afd0f5c&tt=1478700882309.137.192.205" width="300" height="250" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="border-width: 0px; border-style: initial; vertical-align: bottom; margin: 0px;"></iframe>

关于二级指针和二维数组两者差别很大,不可以直接用二级指针传递二维数组

首先来看看二维数组在内存中是如何组织的呢?

一维数组 T arr1 = new T[9]  二维数组T arr2 = new T[3][3]



实际上,不管是一维还是多维数组,都是内存中一块线性连续空间,因此在内存级别上,其实都只是一维。但是不同的定义使得表现形式不一样,从而有多维数组的概念。访问数组元素其实非常简单,原因就在于元素在内存中的线性排列,这样对一维数组的访问只需要arr1[index] = *(arr1+index*sizeof(T));对二维数组的访问

arr2[i][j]=*(arr2+(i*col+j)*sizeof(T)),因此连续线性的数组访问效率很高。多维类似。

下面一个程序测试:

#include<cstdio>

/************************************************************************/

/* 数组和指针参数是如何被编译器修改的?

  “数组名被改写成一个指针参数”规则并不是递归定义的。数组的数组会被改写成“数组的指针”,而不是“指针的指针”:

  

  实参                                                所匹配的形参

 

数组的数组            char c[8][10];                char (*c)[10];        数组指针

  

指针数组              char *c[10];                  char **c;              指针的指针

  

数组指针(行指针)      char (*c)[10];                char (*c)[10];        不改变

    

指针的指针            char **c;                      char **c;              不改变                                                                    */

/************************************************************************/

/*二级指针**作为形参,可以接受二级指针**p、指针数组*p[]作为实参的参数,从而传递二维数组*/

void print(int **p, int row, int col)

{

 int i=0,j=0;

 for(i=0;i<row;i++)

 {

  for(j=0;j<col;j++)

  {

   printf("%d\t",p[i][j]);

  }

 }

 printf("\n");

}

/*数组指针(*)[]作为形参,可以接受数组指针(*p)[3]作为实参的参数,从而传递二维数组*/

void print(int (*p)[3], int row, int col)

{

 int i=0,j=0;

 for(i=0;i<row;i++)

 {

  for(j=0;j<3;j++)

  {

   printf("%d\t",p[i][j]);

  }

 }

 printf("\n");

}

/*function 'void __cdecl print(int ** ,int,int)' already has a body Error executing cl.exe.

/*同二级指针*/

/*

void print(int *p[], int row, int col)

{

 int i=0,j=0;

 for(i=0;i<row;i++)

 {

  for(j=0;j<col;j++)

  {

   printf("%d\t",p[i][j]);

  }

 }

 printf("\n");

}

*/

/******以上两个函数无法重载overload,说明编译器把*p[]和**p  都当成一种类型******************************************/

int main()

{

 int i = 0;

 int **pointer_to_pointer;

 //printf("%X\n",*pointer_to_pointer);//会错误,因为pointer_to_pointer 还未初始化,是野二级指针

 

 int *pointer = new int[9];

 

 int *pointer_array[3]; //指针数组,即是一个存放指针元素的数组,定义后即会有含有三个指针元素的数组,但是每个指针元素并没有初始化

 printf("%X\t%X\t%X\n",pointer_array,pointer_array+1,pointer_array+2);

 printf("%X\t%X\t%X\n",pointer_array[0],pointer_array[1],pointer_array[2]);

 

 int bi_array[3][3] = {{1,2,3},{4,5,6},{7,8,9}};

 int (*array_pointer)[3] = bi_array;//数组指针,指向数组的指针,可用于函数传递二维数组

 int single_array[3] = {1,2,3};

   //pointer_to_pointer = bi_array;  //!!! 错误,二级指针和二维数组首地址(实际内存空间不管是N维数组,都是一片连续的线性空间,二维数组元素访问a[i][j]是a+sizeof(type)*(C*i+j),因此a可以看成是一个指针而已)不是一个东西,二者不能相互赋值

          //cannot convert from 'int [3][3]' to 'int ** '

 //pointer_to_pointer = (int**)bi_array; // !!!慎用,因为虽然没有语法错误,但是会出现内存访问错误;

    //pointer_array = bi_array;//错误cannot convert from 'int [3][3]' to 'int *[3]'

 

 

 //pointer_to_pointer = bi_array+1;//错误cannot convert from 'int (*)[3]' to 'int ** '

 /*******************以上说明二维数组和二维指针不是等价的,不能相互赋值*************************************************/

 

 pointer_to_pointer = pointer_array;

 /*******以上这句说明指针数组*[]  可以转换为二级指针** 他们相互等价*****************************************************/

 

 //pointer = bi_array;//错误cannot convert from 'int [3][3]' to 'int *'

 pointer = (int *)bi_array;

 for(i=0;i<9;i++)

 {

  printf("%d\t",pointer[i]);

 }

 printf("\n");

 

 

 //pointer = array_pointer;//错误cannot convert from 'int (*)[3]' to 'int *'

 pointer = (int *)array_pointer;

 for(i=0;i<9;i++)

 {

  printf("%d\t",pointer[i]);

 }

 printf("\n");

 for(i=0;i<9;i++){pointer[i] = 9;}    //此时指向bi_array的array_pointer的元素被pointer修改为9

 array_pointer = (int(*)[3])pointer;

 print(array_pointer,3,3);

 /********以上说明二维数组名和数组指针虽然是一个指针,但编译器并不理解,对他来说是数组类型的指针,但可以类型强制转换*****/

 

 for(i=0;i<3;i++)

 {

  pointer_array[i] = bi_array[i];

 }

 printf("\n");

 print((int(*)[3])pointer,3,3);

 print(pointer_to_pointer, 3 ,3);

 print(pointer_array, 3, 3);

 return 0;

}

对二维数组做如下总结:

1.二维数组和二维指针不是等价的,不能相互赋值

2.指针数组*[] 可以转换为二级指针** 他们相互等价

3.二维数组名和数组指针虽然是一个指针,但编译器并不理解,对他来说是数组类型的指针,但可以类型强制转换

pointer = (int *)array_pointer;    array_pointer = (int(*)[3])pointer;  pointer = (int *)bi_array;

4.如果想用函数传递二维数组,一般形参用二级指针**p或指针数组*[],可以支持二级指针和指针数组的实参传递,特殊的还可以用(*p)

------------------------------分割线------------------------------

C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码 http://www.linuxidc.com/Linux/2014-05/101227.htm

读C++ Primer 之构造函数陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm

读C++ Primer 之智能指针 http://www.linuxidc.com/Linux/2011-08/40177.htm

读C++ Primer 之句柄类 http://www.linuxidc.com/Linux/2011-08/40175.htm

将C语言梳理一下,分布在以下10个章节中:

Linux-C成长之路(一):Linux下C编程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
Linux-C成长之路(二):基本数据类型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
Linux-C成长之路(三):基本IO函数操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
Linux-C成长之路(四):运算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
Linux-C成长之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
Linux-C成长之路(六):函数要义 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
Linux-C成长之路(七):数组与指针 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
Linux-C成长之路(八):存储类,动态内存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
Linux-C成长之路(九):复合数据类型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
Linux-C成长之路(十):其他高级议题
本文永久更新链接地址http://www.linuxidc.com/Linux/2015-03/115055.htm 



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: