非常感謝這些有用的教程,我覺得有必要寫這篇關於指標和陣列的文章。不幸的是,糾正人們腦海中錯誤的觀念有點困難。因此,準確地理解事物非常重要,以避免進一步的誤解。
陣列不等於指標。它是在記憶體中一系列簡單的變數。
當我們寫
1 2
|
int array[3];
array[2]=666;
|
C/C++ 編譯器不將 array[0] 視為指向整數值的地址,而是直接將其視為一個值,就像寫一樣
顯而易見,“var”不是指標,就像 array[2] 不是一樣。
但是,如果我們使用指標而不是陣列,程式碼的表象是相同的,但編譯器會生成不同的彙編程式碼。例如
1 2
|
int *ptr = new int[3];
ptr[2] = 66;
|
與第一段程式碼類似,但對編譯器而言含義不同。在第一段程式碼(第二行)中,編譯器生成的程式碼將執行以下操作
1)轉到 array[0] 下兩個位置,並將其值設定為 666。
但在使用指標的程式碼中是
1)獲取 ptr[0] 的值(地址)。
2)在其上加二。
3)將其指向的值設定為 66。
實際上,“array”、“&array”和“&array[0]”的值是相等的。但是“&array”的型別是不同的(指向陣列的記憶體地址,而不是陣列的成員)。
這裡是另一個例子,使文章更容易理解。我想寫一個程式,從使用者那裡獲取一個整數,加 4,然後列印結果。一次使用整數指標,一次使用整數變數。
使用整數變數將是
1 2 3 4 5 6 7
|
#include<iostream>
main(){
int int_input;
cin>>int_input;
cout<<(int_input + 4)<<endl;
return 0;
}
|
使用指標將是
1 2 3 4 5 6 7 8
|
#include<iostream>
main(){
int *int_ptr = new int[1];
cin>>*int_ptr;
cout<< (*int_ptr + 4)<<endl;
delete(int_ptr);
return 0;
}
|
誰認為這些程式完全相同?
讓我們看看它們的彙編。對於第一個使用整數變數的程式碼是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
2212: main(){
00401000 push ebp
00401001 mov ebp,esp
00401003 sub esp,44h
00401006 push ebx
00401007 push esi
00401008 push edi
2213: int int_input;
2214: cin>>int_input;
00401009 lea eax,[ebp-4]
0040100C push eax
0040100D mov ecx,offset cin (00414c58)
00401012 call istream::operator>> (0040b7c0)
2215: cout<<(int_input+4)<<endl;
00401017 push offset endl (00401070)
0040101C mov ecx,dword ptr [ebp-4]
0040101F add ecx,4
00401022 push ecx
00401023 mov ecx,offset cout (00414c18)
00401028 call ostream::operator<< (0040b3e0)
0040102D mov ecx,eax
0040102F call ostream::operator<< (00401040)
2216: return 0;
00401034 xor eax,eax
2217: }
|
而對於使用指標的程式碼是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
2212: main(){
00401000 push ebp
00401001 mov ebp,esp
00401003 sub esp,4Ch
00401006 push ebx
00401007 push esi
00401008 push edi
2213: int *int_ptr = new int[1];
00401009 push 4
0040100B call operator new (004011b0)
00401010 add esp,4
00401013 mov dword ptr [ebp-8],eax
00401016 mov eax,dword ptr [ebp-8]
00401019 mov dword ptr [ebp-4],eax
2214: cin>>*int_ptr;
0040101C mov ecx,dword ptr [ebp-4]
0040101F push ecx
00401020 mov ecx,offset cin (00414c38)
00401025 call istream::operator>> (0040b8a0)
2215: cout<< (*int_ptr + 4)<<endl;
0040102A push offset endl (004010a0)
0040102F mov edx,dword ptr [ebp-4]
00401032 mov eax,dword ptr [edx]
00401034 add eax,4
00401037 push eax
00401038 mov ecx,offset cout (00414bf8)
0040103D call ostream::operator<< (0040b4c0)
00401042 mov ecx,eax
00401044 call ostream::operator<< (00401070)
2216: delete(int_ptr);
00401049 mov ecx,dword ptr [ebp-4]
0040104C mov dword ptr [ebp-0Ch],ecx
0040104F mov edx,dword ptr [ebp-0Ch]
00401052 push edx
00401053 call operator delete (00401120)
00401058 add esp,4
2217: return 0;
0040105B xor eax,eax
2218: }
|
19 行 vs 32 行。因此,您可以看到,整數與“指向整數的指標”是不同的。整數是儲存整數的記憶體位置,而整數指標(指向整數的指標)是儲存地址的記憶體位置。編譯器知道這是一個指向儲存整數的記憶體位置的地址。我不會解釋彙編程式碼,因為這篇文章是為初學者準備的,我想保持簡短。
正如我所說,陣列是記憶體中一系列變數。在上面的例子中,我得出結論,指標不是整數變數,因此它也不可能是它們的序列。
請隨時傳送您對本文的評論和想法。