天天看點

【踩坑記錄】【C/C++】數組名與指針的關系;數組名取位址;數組名的解引用與取位址;

文章目錄

    • 前序知識
    • 指針與數組名的差別
      • 驗證
      • 一維數組
      • 二維數組
    • 參考

前序知識

  1. 擷取變量類型的語句是:

    typeid(variable).name()

  2. sizeof 是個關鍵字,在編譯階段起作用。
  3. sizeof 數組名,得到的是數組的位元組大小。

指針與數組名的差別

  • C專家程式設計 中有講到,
  • 數組和指針在編譯器處理時是不同的,在運作時的表示形式也是不一樣的,并可能産生不同的代碼。對編譯器而言,一個數組就是一個位址,而一個指針就是一個位址的位址。
  • 數組名是不可修改的左值,不能直接對其指派(定義時除外)。但可以用memcpy,strcpy等來進行間接“指派”。
  • 講到三個規定
  1. “表達式中的數組名被編譯器當作一個指向該數組第一個元素的指針。”
  2. "下标總是與指針的偏移量相同。
  3. “在函數參數的聲明中,數組名被編譯器當作指向該數組的第一個元素的指針。”(作為形參,數組名退化為指針)
  • 講到三個例外
  1. 數組作為sizeof()的操作數,顯然此時需要的是整個數組的大小,而不是所指向第一個元素的大小
  2. 使用&操作符取數組的位址
  3. 數組是一字元串常量初始化值

驗證

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

(arr2)

數組名:指向第一行的指針(二維指針常量) int [3]

(&arr2)

一維數組的指針;(數組指針) int (*)[3]

(arr2+1)

數組指針+偏移;(指針) int *

(*arr2)

數組名解引用;(值) int

(*arr2+1)

數組名解引用+偏移;(值)(和下面一緻;先解引用) int

((*arr2 )+1

數組名解引用+偏移;(值) int

二維數組

  • arr[i][j]

name meaning type

(arr)

數組名:指向第一行的指針;(二維指針常量)

int [3][3]

(arr + 1)

數組名+偏移;(指向一維數組的指針)

int (*)[3]

(*arr)

數組名解引用;(一維指針常量)

int [3]

(*arr + 1)

數組名解引用+偏移;(指針)

int *

(*(arr + 1))

數組名+偏移 +解引用;一維指針常量

int [3]

(&arr)

數組名取位址;(指向二維數組的指針)

int (*)[3][3]

(&arr+1)

數組名+偏移+取位址;(指向二維數組的指針)

int (*)[3][3]

  • tips:

若要快速得到一個二維數組最後一個元素的值可以這樣

int *ptr = (*int)(&arr + 1);
cout << *(ptr - 1) << endl;
           
  • arr

    隻是arr[0]的位址,arr+1就是arr[1]的位址了.
  • &arr

    是整個arr[10]的首位址,是以整個數組為角度來看,雖然它與arr[0]的值相同,但是&arr+1就已經增加了10個int類型的位元組的長度了.
    【踩坑記錄】【C/C++】數組名與指針的關系;數組名取位址;數組名的解引用與取位址;
  • 即,對數組名取位址,得到的是數組名所指元素的位址。和指針不同;(編譯器特性)

參考

【C專家程式設計】

https://blog.csdn.net/hmxz2nn/article/details/80157461

繼續閱讀