• 文章
  • 指標和陣列的區別
釋出
2008年1月14日

指標和陣列的區別

評分:3.5/5 (40 票)
*****
指標和陣列的區別

我看到很多地方將陣列介紹為指標。這在技術上是不正確的。陣列不是指標。那麼它是什麼?它就像 C++ 中的任何其他變數一樣。
看看這段程式碼

1
2
int arr[3]={3,4,5};
cout<<arr;


你可能會說:“看那裡,arr 是一個地址,誰說它不是指標?”
我說:這段程式碼列印了一個地址。那麼 var 是一個地址嗎?

1
2
int var;
cout<<&var;


讓我解釋一下
所有變數都可以透過它們的地址在記憶體中進行操作。CPU 使用這些地址來獲取它們、更改它們和儲存它們。所以,所有變數都有一個地址(不僅僅是你指向的那些)。我們可以透過 (&) 運算子找到變數的地址,形式如下:

1
2
int* ptr=&intvar;
// Now the address of intvar is in ptr 


陣列只是一系列變數。但是有一個規則,C++ 將陣列視為指標。這是什麼意思?這意味著如果你寫 arr,編譯器會將其視為 &arr[0](除了我稍後會告訴你的三個條件),即陣列第一個元素的地址。它的型別是“指向 T 的指標”,其中 T 是陣列元素的型別(在本例中為 int)。如果你給它加 1,它將指向陣列的第二個元素。

那麼它會把 &arr 當作什麼?
這是規則不適用的例外情況之一。它將其視為“指向陣列的指標”。它仍然指向陣列的第一個元素,但是如果你給這個指標加一,它將指向陣列最後一個元素之後的記憶體地址(就像你跳過了整個陣列一樣)。它是一個指向整個陣列的指標。&arr 和 arr 的值是相同的(第一個元素的地址)。但它們的型別不同。這裡 &arr 的型別是“指向 T 陣列的指標”(與 arr 的型別進行比較)。

看這個

1
2
3
4
5
int arr[3]={3,4,5};
cout<<"First element of the array: "<<arr[0] <<endl;
cout<<"Address of the first element: "<<&arr[0] <<endl;
cout<<"Address of the array: "<<arr <<endl;
cout<<"So what is this? "<<&arr <<endl;


第一個 cout:列印 arr[0] 的“值”。
第二個 cout:列印 arr[0] 的“地址”。
第三個 cout:再次列印 arr[0] 的“地址”。
第四個 cout:列印陣列的地址,也就是 arr[0] 的地址。

還有這個

1
2
3
4
5
int arr[3]={3,4,5};
cout<<"First element of the array: "<<arr[0]+1 <<endl;
cout<<"Address of the first element: "<<&arr[0]+1 <<endl;
cout<<"Address of the array: "<<arr +1<<endl;
cout<<"So what is this? "<<&arr +1<<endl;


第一個 cout:列印 arr[0] 加一的“值”。
第二個 cout:列印 arr[1] 的“地址”。
第三個 cout:再次列印 arr[1] 的“地址”。
第四個 cout:列印陣列之後第一個記憶體地址。


比較
相似之處,每個都有一個例子
1) (*) 可用於兩者。

1
2
3
4
5
6
7
8
int arr[3]={1,3,4};         //Declares an array with 3 elements
int * ptr=arr;              //Initialize pointer ptr with the address of  array arr 
cout<<*(arr+2)<<endl;
cout<<*{ptr+2)<<endl;

/* output */
4
4


2) 訂閱(索引)可用於兩者

1
2
3
4
5
6
7
8
int arr[3]={1,3,4};         //Declares an array with 3 elements
int * ptr=arr; 		 //Initialize pointer ptr with the address of  array arr
cout<<arr[2])<<endl;
cout<<ptr[2])<<endl;

/* output */
4
4


3) 指標可用作陣列。
1
2
3
4
5
6
7
int *ptr=new int[3]; 
ptr[0]=12;
ptr[2]=3;
cout<<ptr[2];

/* output */
3


4) 陣列可以具有指標型別。這意味著它的元素可以是指標。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int ar[2]={8,2};
int var1=66;
int var2=111;
int* ptarray[5];
ptarray[0]=ar;
ptarray[1]=&ar[1];  //Address of second element of array ar
ptarray[2]=&var1;
ptarray[3]=&var2;
ptarray[4]=&ar[0];
// To keep code small I use a loop
for(int i=0;i<5;i++)
	cout<<*(ptarray<i>)<<endl;

/* output */
8
2
66
111
8


5) 所有陣列都將作為指標傳遞給函式,這意味著你實際上不能將陣列傳送到函式。所以 function(char[]) 等同於 function(char*)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;
void test(char v[]);

int main(){ 
	char a[53];
         //a="If a is an array, this line should generate an error";   	
	test(pta);
	return 0;
}

void test(char v[]){
	v="If v is an array, this line should generate an error";
	cout<<v<<endl;
}


不同之處

1) 指標是記憶體中的一個位置,它儲存著另一個位置的地址,而陣列是一個單一的、預先分配的連續元素塊(所有型別都相同),大小和位置固定。

3) 陣列不像指標那樣可以在定義時初始化,但陣列可以。

1
2
char car[3]={'a','b',66}; 
char* cpt=new char[3]; //No way to be initialized here. 


4) 當我們為指標分配記憶體以用作動態陣列時。記憶體以後可以調整大小或釋放。但陣列不是這樣。

例如:

1
2
3
char* pta=new char[12];
//Using pta
delete[] pta;


3) 它們產生不同的彙編程式碼。看看並進行比較

1
2
3
4
5
6
7
8
9
10
int main()
{ 
	char arr[3];
	char* ptr=new char[3];

	arr[0]='C';   //Assembly is for this.  
	ptr[0]='p';   //And for this.

	return 0;
}


會有一個類似這樣的彙編

1
2
3
4
5
6
arr[0]='C';
            mov         byte ptr [ebp-4],43h  //The code for putting one character in an array

ptr[0]='p';
            mov         ecx,dword ptr [ebp-8]  //The two line code for putting one character
            mov         byte ptr [ecx],70h     //in a place where a pointer points to  


希望有所幫助……

參考
http://67.40.109.61/torek/c/index.html
http://c-faq.com/questions.html