關於二級指針和二維數組兩者差別很大,不可以直接用二級指針傳遞二維數組
首先來看看二維數組在內存中是如何組織的呢?
一維數組 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個章節中: