指標和陣列的區別
我看到很多地方將陣列介紹為指標。這在技術上是不正確的。陣列不是指標。那麼它是什麼?它就像 C++ 中的任何其他變數一樣。
看看這段程式碼
1 2
|
int arr[3]={3,4,5};
cout<<arr;
|
你可能會說:“看那裡,arr 是一個地址,誰說它不是指標?”
我說:這段程式碼列印了一個地址。那麼 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