文章目錄
-
- 前序知識
- 指針與數組名的差別
-
- 驗證
- 一維數組
- 二維數組
- 參考
前序知識
- 擷取變量類型的語句是:
;typeid(variable).name()
- sizeof 是個關鍵字,在編譯階段起作用。
- sizeof 數組名,得到的是數組的位元組大小。
指針與數組名的差別
- C專家程式設計 中有講到,
- 數組和指針在編譯器處理時是不同的,在運作時的表示形式也是不一樣的,并可能産生不同的代碼。對編譯器而言,一個數組就是一個位址,而一個指針就是一個位址的位址。
- 數組名是不可修改的左值,不能直接對其指派(定義時除外)。但可以用memcpy,strcpy等來進行間接“指派”。
- 講到三個規定
- “表達式中的數組名被編譯器當作一個指向該數組第一個元素的指針。”
- "下标總是與指針的偏移量相同。
- “在函數參數的聲明中,數組名被編譯器當作指向該數組的第一個元素的指針。”(作為形參,數組名退化為指針)
- 講到三個例外
- 數組作為sizeof()的操作數,顯然此時需要的是整個數組的大小,而不是所指向第一個元素的大小
- 使用&操作符取數組的位址
- 數組是一字元串常量初始化值
驗證
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int arr2[3] = { 2,5,6 };
int(*p)[3] = &arr2;
cout << "(arr) \t" << (arr) << " \t" << sizeof(arr) << "\t" << typeid(arr).name() << endl;
cout << "(arr + 1) \t" << (arr + 1) << " \t" << sizeof(arr + 1) << "\t" << typeid(arr + 1).name() << endl;
cout << "(*arr) \t" << (*arr) << " \t" << sizeof(*arr) << "\t" << typeid(*arr).name() << endl;
cout << "(*arr + 1) \t" << (*arr + 1) << " \t" << sizeof(*arr + 1) << "\t" << typeid(*arr + 1).name() << endl;
cout << "(*(arr + 1))\t" << (*(arr + 1)) << " \t" << sizeof(*(arr + 1)) << "\t" << typeid(*(arr + 1)).name() << endl;
cout << "(&arr) \t" << (&arr) << " \t" << sizeof(&arr) << "\t" << typeid(&arr).name() << endl;
cout << "(&arr+1) \t" << (&arr + 1) << " \t" << sizeof(&arr + 1) << "\t" << typeid(&arr + 1).name() << endl;
cout << "*******************************************************************" << endl;
cout << "(arr2) \t" << (arr2) << " \t" << sizeof(arr2) << "\t" << typeid(arr2).name() << endl;
cout << "(&arr2) \t" << (&arr2) << " \t" << sizeof(&arr2) << "\t" << typeid(&arr2).name() << endl;
cout << "(arr2+1) \t" << (arr2 + 1) << " \t" << sizeof(arr2 + 1) << "\t" << typeid(arr2 + 1).name() << endl;
cout << "(*arr2) \t" << (*arr2) << " \t" << sizeof(*arr2) << "\t" << typeid(*arr2).name() << endl;
cout << "(*arr2+1) \t" << (*arr2 + 1) << " \t" << sizeof(*arr2 + 1) << "\t" << typeid(*arr2 + 1).name() << endl;
cout << "((*arr2 )+1)\t" << ((*arr2) + 1) << " \t" << sizeof((*arr2) + 1) << "\t" << typeid((*arr2) + 1).name() << endl;
cout << "(p) \t" << (p) << " \t" << sizeof(p) << "\t" << typeid(p).name() << endl;
- X86下結果
(arr) 0117F834 36 int [3][3]
(arr + 1) 0117F840 4 int (*)[3]
(*arr) 0117F834 12 int [3]
(*arr + 1) 0117F838 4 int *
(*(arr + 1)) 0117F840 12 int [3]
(&arr) 0117F834 4 int (*)[3][3]
(&arr+1) 0117F858 4 int (*)[3][3]
**********************************************
(arr2) 0117F820 12 int [3]
(&arr2) 0117F820 4 int (*)[3]
(arr2+1) 0117F824 4 int *
(*arr2) 2 4 int
(*arr2+1) 3 4 int
((*arr2 )+1) 3 4 int
(p) 0117F820 4 int (*)[3]
一維數組
-
int arr2[3] = { 1,2,3 };
name | meaning | type |
---|---|---|
| 數組名:指向第一行的指針(二維指針常量) | int [3] |
| 一維數組的指針;(數組指針) | int (*)[3] |
| 數組指針+偏移;(指針) | int * |
| 數組名解引用;(值) | int |
| 數組名解引用+偏移;(值)(和下面一緻;先解引用) | int |
| 數組名解引用+偏移;(值) | int |
二維數組
-
arr[i][j]
name | meaning | type |
---|---|---|
| 數組名:指向第一行的指針;(二維指針常量) | |
| 數組名+偏移;(指向一維數組的指針) | |
| 數組名解引用;(一維指針常量) | |
| 數組名解引用+偏移;(指針) | |
| 數組名+偏移 +解引用;一維指針常量 | |
| 數組名取位址;(指向二維數組的指針) | |
| 數組名+偏移+取位址;(指向二維數組的指針) | |
- tips:
若要快速得到一個二維數組最後一個元素的值可以這樣
int *ptr = (*int)(&arr + 1);
cout << *(ptr - 1) << endl;
隻是arr[0]的位址,arr+1就是arr[1]的位址了.
arr
是整個arr[10]的首位址,是以整個數組為角度來看,雖然它與arr[0]的值相同,但是&arr+1就已經增加了10個int類型的位元組的長度了.
&arr
- 即,對數組名取位址,得到的是數組名所指元素的位址。和指針不同;(編譯器特性)
參考
【C專家程式設計】
https://blog.csdn.net/hmxz2nn/article/details/80157461