歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言中的二級指針和二維數組問題

C語言中的二級指針和二維數組問題

日期:2017/3/1 9:30:54   编辑:Linux編程

關於二級指針和二維數組兩者差別很大,不可以直接用二級指針傳遞二維數組

首先來看看二維數組在內存中是如何組織的呢?

一維數組 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)[N]

------------------------------分割線------------------------------

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個章節中:

  1. Linux-C成長之路(一):Linux下C編程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成長之路(二):基本數據類型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成長之路(三):基本IO函數操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成長之路(四):運算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成長之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成長之路(六):函數要義 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成長之路(七):數組與指針 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成長之路(八):存儲類,動態內存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成長之路(九):復合數據類型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved