[英]Need to understand some pointers in C
好吧,我有一個我們必須在學校使用的簡單示例,但我不明白為什么我們必須使用指針以及它們在相同情況下的作用。
int **create(int lines, int columns)
{
int **p, i;
p = (int **) malloc(lines * sizeof(int *));
for(i = 0; i < lines; i++)
p[i] = (int *) malloc(columns * sizeof(int));
return p;
}
我谷歌**
是指向指針的指針。 簡單地指向已存儲變量地址的指針的指針。 但為什么我應該這樣做? 然后這兩行代碼看起來有完全隨機的指針
p = (int **) malloc(lines * sizeof(int *));
p[i] = (int *) malloc(columns * sizeof(int));
基本上我知道指針指向變量的地址或其他東西,但不知道這里發生了什么。 請有人向我解釋一下。 謝謝你的時間。
指針也可以理解為數組。 您可以使用malloc
分配一些空間,並且可以使用[]
運算符設置項目,就像數組一樣。
int* arr = (int*)malloc(sizeof(int)*3);
arr[1] = 5;
printf("%d", arr[1]); //output is 5
指向指針的指針可以理解為二維數組:您為指針分配空間,然后將每個指針分配為一個數組。
int** arr = (int**)malloc(sizeof(int*) * 3);
for (int i = 0; i < 3; i++) {
arr[i] = (int*)malloc(sizeof(int) * 3); // each element is going to be an array of 3 integers
}
arr[2][2] = 4;
printf("%d", arr[2][2]); // 4
此函數創建一個矩陣,它是一個二維數組。
數組是連續存儲在內存中的元素序列。 使用malloc
我們分配了一個可以用作數組的內存塊。 然后我們持有一個指向元素塊的指針。 然后我們可以使用符號a[i]
來標識數組的第 i 個元素,其地址存儲在a
。
表達式malloc(n * sizeof(int));
為n
整數分配一個內存塊。 請注意,它返回一個指向整數的指針: int *
。
當我們創建一個二維數組時,每一行都是一個用上述指令分配的數組。 n
被列數替換。
然后將所有行與一組數組捆綁在一起。 請記住,數組的類型是int *
。 因此,數組數組以int *
值作為元素。 它的類型是int **
。
代碼中的第一個malloc
分配將保存所有行數組的數組。 這就是為什么它的類型是int **
。 它的字節大小是lines
int *
的字節大小。
在for
循環中,每一行都被實例化並分配給數組p
的相應元素。
返回的二維數組令人愉快的事情是,您可以通過表達式a[i][j]
識別其元素。
請注意,這段代碼有一個錯誤。
for 循環是for(i = 0; i < riadky; i++)
。 riadky
是一個未定義的變量。 這不是正確的變量名。
現在您希望理解代碼,您能找到正確的變量名嗎? 你應該能夠從我的解釋中找到它。
一些圖片應該會有所幫助。
我們從對象p
開始:
int **
+–––+
p: | |
+–––+
p
類型為int **
,這意味着它可以存儲類型為int *
的對象的地址。
為簡單起見,我們假設lines
和columns
都是2
。 因此,我們首先為兩個int *
類型的對象動態分配足夠的空間,並將這些對象中p
一個的地址存儲到p
:
int ** int *
+–––+ +–––+
p: | | ––––––> | |
+–––+ +–––+
| |
+–––+
數組下標操作a[i]
定義為*(a + i)
- 給定起始地址a
,從該地址1偏移i
元素(不是字節)並取消引用結果2 。 所以表達式p[0]
指的是第一個元素,而p[1]
指的是第二個:
int ** int *
+–––+ +–––+
p: | | ––––––> | | p[0]
+–––+ +–––+
| | p[1]
+–––+
現在,對於每個p[i]
,我們為 2 個int
對象分配足夠的空間,並將每個集合中p[i]
一個的地址分配給p[i]
:
int ** int * int
+–––+ +–––+ +–––+
p: | | ––––––> | | p[0]-––> | | p[0][0]
+–––+ +–––+ +–––+
| | p[1]–+ | | p[0][1]
+–––+ | +–––+
|
| +–––+
+-> | | p[1][0]
+–––+
| | p[1][1]
+–––+
至於為什么需要使用多個間接級別( **
、 ***
等)...
對於任何類型為T
對象E
,表達式&E
計算結果為該對象的地址,並且該表達式的類型為T *
(指向T
指針)。 如果我們用指針類型P *
替換T
,則&E
的類型是P **
。 IOW,保存另一個對象地址的對象的類型必須比指向的對象多一級間接。
p
類型為int *
並指向一個int
對象,則p+1
指向緊隨其后的下一個int
對象,無論該對象是 2、4 還是更多字節。a
地址?” 除非它是sizeof
或一元&
運算符的操作數,或者是用於在聲明中初始化字符數組的字符串文字,否則類型為“ T
N 元素數組”的表達式將被轉換(“衰減”)為“指向T
指針”類型的表達式,表達式的值將是第一個元素的地址。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.