數組名、指標和地址,數組指標地址
首先看這個:
#include <stdio.h>#include <iostream>using namespace std;int main() { int a[2] = {1, 2}; cout << "The address of int_array: " << endl; cout << a << " " << &a << endl << endl; double b[2] = {1.2, 1.3}; cout << "The address of double_array: " << endl; cout << b << " " << &b << endl << endl; char c[2] = {'a', 'b'}; cout << "The address of char_array: " << endl; cout << c << " " << &c << endl << endl; int d[5] = {1, 2, 3, 4, 5}; int dd[5] = {6, 7, 8, 9, 0}; int j = 2, k = 1, i = 3; cout << d[i] << " " << i[d] << endl << endl; //this code is so strange, but in fact, d[i] = *(d + i) = *(i + d) = i[d]. return 0;}
這裡發現,a和&a好像是一樣的,還有char類型的怎麼就不一樣?
首先是關於a和&a:
#include <stdio.h>int main() { int a[5] = {1, 2, 3, 4, 5}; printf("a = %p\n", a); printf("&a = %p\n", &a); printf("a + 1 = %p\n", a + 1); printf("&a + 1 = %p\n", &a + 1); return 0;}
顯然,a是數組第一個元素的地址,而&a指的是整個數組(兩者長度根本不同)
後來自己寫了些東西:
#include <iostream>using namespace std;int main() { int a[5] = {305210130, 1164203589, 2023197048, 4, 5};//前三個數字在十六進位中表示分別是12312312、45645645、78978978,這樣寫主要為了測試方便 int *ptr1 = (int *)(&a + 1); int *ptr2 = (int *)((int)a + 1); for (int i = 0; i < 20; i++) {//01 cout << hex << *(int *)((int)a + i) << dec << ' '; } cout << endl << endl; cout << "&a + 1 : " << &a + 1 << endl;//02 cout << "*(&a + 1) : " << *(&a + 1) << endl;//03 cout << "**(&a + 1) : " << **(&a + 1) << endl;//04 cout << "*(a + 5) : " << *(a + 5) << endl;//05 cout << "(int *)(&a + 1) : " << (int *)(&a + 1) << endl;//06 cout << "*((int *)(&a + 1)) : " << *((int *)(&a + 1))<< endl;//07 cout << "*ptr1 : " << *ptr1 << endl;//08 cout << "ptr1 : " << ptr1 << endl;//09 cout << "ptr1[-1] : " << ptr1[-1] << endl;//10 cout << "ptr1[-5] : " << ptr1[-5] << endl;//11 cout << "(int)a : " << (int)a << endl;//12 cout << "(int)a + 1 : " << (int)a + 1 << endl;//13 cout << "(int *)((int)a + 1) : " << (int *)((int)a + 1) << endl;//14 cout << "the address of a's first element : " << a << endl;//15 cout << "*ptr2 : " << *ptr2 << endl;//16 cout << "ptr2 : " << ptr2 << endl;//17 cout << "the hex of *ptr2(*ptr2 = (int *)((int)a + 1)) : " << hex << *ptr2 << dec << endl;//18 ptr2 = (int *)((int)a + 3);//19 cout << "the hex of *ptr2(*ptr2 = (int *)((int)a + 3)) : " << hex << *ptr2 << dec << endl;//20 return 0;}
現在來試著解釋一下,解釋點對應代碼中的注釋序號:01、http://www.cnblogs.com/y041039/archive/2012/04/11/2442345.html這篇部落格裡對資料的儲存做了很好地說明,可以解釋這一點我的電腦用的顯然是Little Endian,這麼一來,實際資料為:(十六進位下)12 31 23 12 45 64 56 45 78 97 89 78 00 00 00 04 00 00 00 05記憶體中的資料應為:(第一行是標號,第二行是資料,同樣在16進位下)0x22ff————2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 12 23 31 12 45 56 64 45 78 89 97 78 04 00 00 00 05 00 00 00 ?? ?? ?? ??另外一點要瞭解的是,*(int *)((int)a + i)的意思,(int)a將a的地址轉化成int類型(注釋12), 然後(int)a + 1是地址加一,這個一是真正的一,不按照int的大小加四(注釋13),(int *)((int)a + i)再將int類型的地址轉化為指向int的地址(也就是16進位),也就是0x22ff31(注釋14),最後取內容。那麼輸出結果也就明白了:0x22ff30: 123123120x22ff31: 451231230x22ff31: 56451231...注意高位的零被省略了:0x22ff3a: 00047897——>47897
02、這裡指出了&a的含義:依然是數組的地址(特殊的地址),但是表示了長度,所以後面的加一直接加上了一個數組的長度(也就是20, 轉化為十六進位就是14),輸出就是0x22ff30 + 14;
03、這裡就說明了02中&a的特殊性,相當於自己指向自己?所以取內容仍然是自己;
04、取兩次,取第一次是地址,再來一次是地址上的內容;
05、這裡是為了驗證04的正確性;
06到11都是對上述的實驗,注意ptr1的類型決定了地址位移的大小(-1就是-1個int長度);
12到15還行吧,不太難;
16、這個時候ptr2的地址是0x22ff31那麼由01中的解釋,*ptr2就是45123123,轉化為十進位就是1158820131;
17、16中已講到;
剩下的幾個就是對01的驗證了。
注意到這麼一道題:
這麼一來就沒什麼問題了,&a + 1指的是數組最後一位的下一個地址,而ptr1[-1] = *(ptr1 + (-1)),也就是數組最後一位,內容是5;而這個時候的數組值為:(注意進位)00 00 00 01 00 00 00 02 00 00 。。。在記憶體中:(注意進位)01 00 00 00 02 00 00 00 03 00 。。。這樣一來a的地址對應的是上面的第三個00,轉化為int,加一(真正的一),也就是第三個00的下一個——02,再將它轉化為指向int的,也就是00 00 00 02,真實值(16進位)02000000,也就是2000000。