[英]Working of Pointers and Arrays in C
我正在使用Visual Studio 2013 for C.
main.c中
int main()
{
int arr[2][3] = { { 10, 20, 30 }, { 15, 25, 35 } };
int **pArr = arr;
printf("\n\n----SIZE OF----");
printf("\nSizeOf(arr) = %d", sizeof(arr));
printf("\nSizeOf(pArr) = %d", sizeof(pArr));
printf("\n\n----DEREFERENCING THE ADDRESS----");
printf("\narr = %d *arr = %d **arr = %d", arr, *arr, **arr);
printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
return 0;
}
檢出此圖像以查找拋出的異常:
使用斷點時,將顯示指針pArr
和數組arr
中的值:
但是,當我從代碼的第二行中刪除**pArr
部分時,程序將輸出以下內容:
----SIZE OF----
SizeOf(arr) = 24
SizeOf(pArr) = 4
----DEREFERENCING THE ADDRESS----
arr = 5569760 *arr = 5569760 **arr = 10
pArr = 5569760 *pArr = 10
指針pArr
的類型為“指向int的指針”,因此它是arr
的地址。 那為什么在使用int **pArr = arr;
后為什么不能訪問**pArr
int **pArr = arr;
?
因為*pArr
產生2D數組的第一個元素10,所以會出現錯誤。
然后,通過在最后一個printf
寫入**pArr
,您嘗試取消引用以十六進制0xa
表示的10,從而出現錯誤消息。
更改
int **pArr = arr;
至
int *Arr = arr;
int **pArr = &Arr;
由於pArr
是一個指向int
類型的指針的指針,因此您試圖將其僅指向一個指針。 因此,當嘗試取消引用未知的內存位置時,會導致Segmentation fault
編輯:
考慮int arr[]
;
這里&arr
和arr
是內存位置。 (arr + 2)來獲取arr [2]的地址,而不是((&arr)+2)來獲取相同的地址。 同樣, pArr
指向arr
。 當您編寫*pArr
它與**arr
相同
請參閱差異以了解更多信息
您的數組arr
和pArr
包含地址0x60f914
。 您已初始化的內存中包含6個整數。
當您執行*pArr
,它將在地址0x60f914
處包含10
。 當您執行**pArr
,它將在地址10
處包含您的內容。
因此,得出的結論是二維數組未完全按照_pointer-to-pointer-int的形式排列。
更新:
這類似於類型轉換。 如果您有一些內存地址(例如void *
),則可以將其類型轉換為任何內容( int *
或my_struct *
)並訪問其中的內容。 但這不能保證該結構及其包含的內存對於您嘗試執行的類型轉換有效。
如果使用一維數組,則arr
是指向數組arr的基值的指針。 這&arr[0]
一樣好。
使用二維數組時,arr表示指向基值的指針,即arr[0]
,它是(*arr)[3]
。
所以你應該使用
int (*pArr)[3] = arr;
代替
int **ptr = arr;
多維數組是編譯器構造。 它是一個連續的內存區域,其位置由編譯器提取。 計算機的物理內存布局純粹是一維的(巨大的數組)。
因此,以下代碼:
int **pArr = arr;
它翻譯為以下程序集:
6:hhh1.c **** int **pArr = arr;
41 .loc 1 6 0
42 0032 488D45E0 leaq -32(%rbp), %rax
43 0036 488945D8 movq %rax, -40(%rbp)
和以下(正確)代碼:
int (*pArr)[3] = arr;
在以下程序集中翻譯:
6:hhh2.c **** int (*pArr)[3] = arr;
41 .loc 1 6 0
42 0032 488D45E0 leaq -32(%rbp), %rax
43 0036 488945D8 movq %rax, -40(%rbp)
驚訝的是它翻譯的完全一樣!? 這是因為第二個代碼更改了編譯器稍后在代碼上獲取內存的方式。
讓我們看一下最后一個或您自己的printf的匯編,第一個是錯誤的代碼,第二個是正確的代碼:
14:hhh1.c **** printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
71 .loc 1 14 0
72 00a0 488B45D8 movq -40(%rbp), %rax
73 00a4 488B00 movq (%rax), %rax
74 00a7 8B08 movl (%rax), %ecx
75 00a9 488B45D8 movq -40(%rbp), %rax
76 00ad 488B10 movq (%rax), %rdx
77 00b0 488B45D8 movq -40(%rbp), %rax
78 00b4 4889C6 movq %rax, %rsi
79 00b7 BF000000 movl $.LC5, %edi
79 00
80 00bc B8000000 movl $0, %eax
80 00
81 00c1 E8000000 call printf
現在,通過使用第二種樣式生成:
14:hhh2.c **** printf("\npArr = %d *pArr = %d **pArr = %d", pArr, *pArr, **pArr); //EXCEPTION thrown here
71 .loc 1 14 0
72 00a0 488B45D8 movq -40(%rbp), %rax
73 00a4 8B08 movl (%rax), %ecx
74 00a6 488B55D8 movq -40(%rbp), %rdx
75 00aa 488B45D8 movq -40(%rbp), %rax
76 00ae 4889C6 movq %rax, %rsi
77 00b1 BF000000 movl $.LC5, %edi
77 00
78 00b6 B8000000 movl $0, %eax
78 00
79 00bb E8000000 call printf
哇! 現在看到嗎 這不一樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.