簡體   English   中英

需要理解C中的一些指針

[英]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 *的對象的地址。

為簡單起見,我們假設linescolumns都是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,保存另一個對象地址的對象的類型必須比指向的對象多一級間接。


  1. 指針算法在對象方面起作用,而不是字節。 如果p類型為int *並指向一個int對象,則p+1指向緊隨其后的下一個int對象,無論該對象是 2、4 還是更多字節。
  2. “但大家都說數組不是指針,是如何a地址?” 除非它是sizeof或一元&運算符的操作數,或者是用於在聲明中初始化字符數組的字符串文字,否則類型為“ T N 元素數組”的表達式將被轉換(“衰減”)為“指向T指針”類型的表達式,表達式的值將是第一個元素的地址。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM