陣列指標 指標陣列

qkk123456789發表於2012-05-30

1、陣列指標(指向陣列的指標)

(1)陣列在記憶體中的表示

建立一個陣列就是在記憶體裡面開闢一塊連續的空間,比如int a[4];就是在記憶體裡面開闢了一個大小為4*sizeof(int)位元組的記憶體空間。二維陣列是特殊的一維陣列。

先來看一段程式碼:

<strong><span style="font-size:16px;">void main()
{
	int a[2][2]={1,2,3,4};//這是一個2*2的二維陣列
    int (*p)[2];//陣列指標
    p=a;//令p指向陣列a
}</span></strong>

注意到程式碼中這句話:int (*p)[2];這裡的p是一個陣列指標變數。

a中各個元素在記憶體中是這樣存放的:

 

(2)理解陣列名和陣列指標變數

OK,現在我們思考a,a[0],a[1],p,a+1,a[0]+1,p+1到底是什麼,思考3秒鐘:

分析:

a是一個陣列名,型別是指向一維陣列的指標,不是變數,a的值是指標常量,即不能有a++或者a=p這些操作。a指向這塊連續空間的首地址,是&a[0][0]。

a[0]是一維陣列名,型別是指向整型的指標,是&a[0][0],這個值是一個常量。

a[1]是一維陣列名,型別是指向整型的指標,是&a[1][0],這個值是一個常量。

p是一個陣列指標變數,指向一維陣列的指標變數是&a[0][0]。可以執行p++;p=a等操作。

a+1表示指向下一行元素,也可以理解為指向下一個一維陣列。

*(a+1)是取出第一行的首地址。

a[0]+1是指向第0行第1個元素,也可以理解為指向一維陣列a[0]的第一個元素。

p+1同a+1

*(p+1)同*(a+1)

雖然a跟a[0]值是一樣,但型別不一樣,表示的意義不一樣。通過分析就不難理解為什麼*(*(a+i)+j)和a[i][j]等效了。

 

(3)指標是陣列的迭代器

<span style="font-size:16px;">#include<stdio.h>
#define M 2
#define N 3

int main()
{
	int a[M][N]={1,2,3,4,5,6};
	int *start=&a[0][0];
	int * const end=start+M*N;
	for(;start!=end;start++)
		printf("%-5d",*start);
	putchar('\n');
	return 0;
}</span>

理解這段程式碼,用指標遍歷一個二維陣列,是不是很像C++標準庫裡面vector的迭代器。注意這裡只用了一個for迴圈,這也可以說明二維陣列其實就是特殊的一維陣列。

 

(4)陣列名與陣列指標變數的區別

 

從(2)中的分析中得出陣列名是指標,型別是指向元素型別的指標,但值是指標常量,宣告陣列時編譯器會為宣告所指定的元素數量保留記憶體空間。陣列指標是指向陣列的指標,宣告指標變數時編譯器只為指標本身保留記憶體空間。

 

看看這個程式碼:

<strong><span style="font-size:16px;">#include<stdio.h>
void main()
{
	int a[2][2]={1,2,3,4};//這是一個2*2的二維陣列
    int (*p)[2];//陣列指標
    p=a;//令p指向陣列a
	printf("%d\n%d\n",sizeof a,sizeof p);
}</span></strong>

猜一猜輸出是什麼?


困惑了嗎?為什麼結果會是這樣的呢,讓我們先初步瞭解一下sizeof關鍵字吧,下面是MSDN上sizeof的說明:

 



注意到說明中的紅色字型,當sizeof用於變數時返回這個變數佔用的實際空間的大小。當sizeof用於陣列名時,返回整個陣列的大小(這裡的大小指佔用的位元組數)。p是一個指標變數,這個變數佔用四個位元組。而a是陣列名,所以sizeof a返回陣列a中的全部元素佔用的位元組數。

 瞭解了sizeof,猜猜下面這段程式碼輸出什麼

<span style="font-size:16px;"><strong>#include<stdio.h>

void main()
{
	int a[2][2]={1,2,3,4};//這是一個2*2的二維陣列
    int (*p)[2];//陣列指標
    p=a;//令p指向陣列a
    printf("%d\n%d\n",sizeof(a+1),sizeof(p+1));
    printf("%d\n%d\n",sizeof(a+0),sizeof(p+0));
}</strong></span>

執行結果:

從結果中看出,a在做+運算時是轉化成了指標變數,此時a+i的型別是一個指標變數,而不是一個陣列名。但a[i]是一個一維陣列的陣列名,sizeof(a[0])的值是8

 

現在再來看一段程式碼:

<strong><span style="font-size:16px;">#include<stdio.h>

void f(int a[][2])
{
	printf("%d\n",sizeof a);
}
void main()
{
	int a[2][2]={1,2,3,4};//這是一個2*2的二維陣列
	printf("%d\n",sizeof a);
	f(a);
}</span></strong>

再猜一下輸出是什麼?

是不是又有點困惑呢?

解釋:這是因為傳參的時候陣列名轉化成指標變數,注意到函式f中f(int a[][2])這裡並不需要指定二維陣列的長度,此處可以改為int (*a)[2]。所以傳過來的就是一個陣列指標變數。這樣明白了吧!

 

總結:陣列名的型別是指向元素型別的指標,值是指標常量。(a+1)的型別是一個指標變數。把陣列名作為引數傳遞的時候實際上傳遞的是一個指標變數。sizeof對變數和陣列名操作時返回的結果會不一樣。陣列指標是指向陣列的指標,其值可以是變數。

2、指標陣列(存放指標的陣列)

(1)認識指標陣列

一個存放int型別的陣列稱為整型陣列,那麼存放指標的陣列就叫指標陣列。

<strong><span style="font-size:16px;">#include<stdio.h>

void main()
{
	int i=1,j=2;
	//p先跟[]結合,然後再跟*結合
    int *p[2];//指標陣列,存放指標的陣列
	p[0]=&i;
	p[1]=&j;
	printf("%d",sizeof(p));
}</span></strong>

斷點除錯分析:

 

此例陣列p就兩個元素,p[0]是指向i的指標,p[1]是指向j的指標。這兩個指標都是int型指標,所以p是存放int型指標的陣列。sizeof(p)返回陣列佔用的總空間,所以程式輸出是8

 

(2)指標陣列用法舉例

來自《the c programming language》的一個例子,對字串進行排序,看了下面這個例子,相信你就體會到了指標陣列的好處了。

 

 

 3、深入思考

陣列名a、a[0]、a[1],陣列指標p到底在記憶體中是怎麼儲存的呢?存放在記憶體中的哪裡呢?是在程式碼段嗎?求解惑!

 

 4、參考資料

《c和指標》 《the c programming language》 等

源地址:http://blog.csdn.net/touch_2011/article/details/6966980

另外的一篇文章

陣列指標(也稱行指標)
定義 int (*p)[n];
()優先順序高,首先說明p是一個指標,指向一個整型的一維陣列,這個一維陣列的長度是n,也可以說是p的步長。也就是說執行p+1時,p要跨過n個整型資料的長度。

如要將二維陣列賦給一指標,應這樣賦值:
int a[3][4];
int (*p)[4]; //該語句是定義一個陣列指標,指向含4個元素的一維陣列。
 p=a;        //將該二維陣列的首地址賦給p,也就是a[0]或&a[0][0]
 p++;       //該語句執行過後,也就是p=p+1;p跨過行a[0][]指向了行a[1][]

所以陣列指標也稱指向一維陣列的指標,亦稱行指標。

指標陣列
定義 int *p[n];
[]優先順序高,先與p結合成為一個陣列,再由int*說明這是一個整型指標陣列,它有n個指標型別的陣列元素。這裡執行p+1是錯誤的,這樣賦值也是錯誤的:p=a;因為p是個不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它們分別是指標變數可以用來存放變數地址。但可以這樣 *p=a; 這裡*p表示指標陣列第一個元素的值,a的首地址的值。
如要將二維陣列賦給一指標陣列:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
這裡int *p[3] 表示一個一維陣列記憶體放著三個指標變數,分別是p[0]、p[1]、p[2]
所以要分別賦值。

這樣兩者的區別就豁然開朗了,陣列指標只是一個指標變數,似乎是C語言裡專門用來指向二維陣列的,它佔有記憶體中一個指標的儲存空間。指標陣列是多個指標變數,以陣列形式存在記憶體當中,佔有多個指標的儲存空間。
還需要說明的一點就是,同時用來指向二維陣列時,其引用和用陣列名引用都是一樣的。
比如要表示陣列中i行j列一個元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]

 

優先順序:()>[]>*


源地址:http://www.cnblogs.com/hongcha717/archive/2010/10/24/1859780.html


相關文章