2013-10-08 92 views
4

這是我老師向我們介紹的「如何在C中動態分配數組?」的示例代碼。但我不完全明白這一點。下面是代碼:動態分配數組解釋

int k; 
int** test; 
printf("Enter a value for k: "); 
scanf("%d", &k); 
test = (int **)malloc(k * sizeof(int*)); 
for (i = 0; i < k; i++) { 
    test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values 
} 

我想在C,定義一個數組,你不得不把[]名之後,那麼到底是什麼int** test;它不只是一個指針指針?而malloc()這一行也讓我很困惑......

+1

我希望你的老師還展示瞭如何分配multidimenional陣列中的所有自然地打造成了語言,沒」向你展示2D的這個模擬,作爲第一個需要注意的地方和數組和指針。但無論如何,他向你展示了許多令人f目結舌的代碼:在C語言中,你不會施加「malloc」的返回值,並且無論如何你都不會教任何人在語言理解的早期階段使用強制轉換。 –

回答

9

根據聲明int** test;,testpointer to pointer,代碼片使用malloc函數動態地爲int值矩陣分配內存。

聲明:

test = (int **)malloc(k * sizeof(int*)); 
    //    ^^------^^------- 
    // allocate for k int* values  

繼續分配內存k指針爲int(int*)。因此,假設如果k = 4那麼你得到這樣的:

temp  343 347 351 355 
+----+ +----+----+----+----+ 
|343 |---►| ? | ? | ? | ? | 
+----+ +----+----+----+----+ 

我假設地址是四個字節和?意味着垃圾值。

temp由malloc變量賦值的返回地址,malloc分配繼續內存塊的大小= k * sizeof(int**)這是在我的例子= 16字節。

在for循環中,爲k int分配內存,並將返回的地址分配給temp[i](以前分配的數組的位置)。

test[i] = (int*)malloc(k * sizeof(int)); //Initialize all the values 
//      ^^-----^^---------- 
//  allocate for k int values  

注:表達temp[i] == *(temp + i)。所以在每個迭代循環中,您對於k int類型的數組,看起來像下面分配內存:

First malloc      For loop 
    ---------------     ------------------ 
     temp 
     +-----+ 
     | 343 |--+ 
     +-----+ | 
       ▼     201 205 209 213 
     +--------+    +-----+-----+-----+-----+ 
343 |  |= *(temp + 0) | ? | ? | ? | ? | //for i = 0 
     |temp[0] |-------|  +-----+-----+-----+-----+ 
     | 201 |  +-----------▲ 
     +--------+     502 506 510 514 
     |  |    +-----+-----+-----+-----+ 
347 |temp[1] |= *(temp + 1) | ? | ? | ? | ? | //for i = 1 
     | 502 |-------|  +-----+-----+-----+-----+ 
     +--------+  +-----------▲ 
     |  |     43 48 52 56 
351 | 43  |    +-----+-----+-----+-----+ 
     |temp[2] |= *(temp + 2) | ? | ? | ? | ? | //for i = 2 
     |  |-------|  +-----+-----+-----+-----+ 
     +--------+  +-----------▲ 
355 |  | 
     | 9002 |     9002 9006 9010 9014 
     |temp[3] |    +-----+-----+-----+-----+ 
     |  |= *(temp + 3) | ? | ? | ? | ? | //for i = 3 
     +--------+  |  +-----+-----+-----+-----+ 
         +-----------▲ 

再次?意味着垃圾值。

其他景點:

1)您是鑄造malloc返回地址,但在C,你應該避免。閱讀Do I cast the result of malloc?只是做如下:

test = malloc(k* sizeof(int*)); 
for (i = 0; i < k; i++){ 
    test[i] = malloc(k * sizeof(int)); 
} 

2)如果你是動態分配的內存,你需要釋放內存明確,當你的工作與完成(釋放動態分配的內存,你不能訪問內存)之後。步驟來釋放內存test將如下:

for (i = 0; i < k; i++){ 
    free(test[i]); 
} 
free(test); 

3)這是,如果你想完全分配的二維矩陣分配內存數組的數組的一種方式繼續存儲所有陣列檢查這個答案:Allocate memory 2d array in function C

4)如果說明幫助和你想學習的3D分配入住這樣的回答:Matrix of String or/ 3D char array

+0

添加鏈接:[** 23.2:動態分配多維數組**](http://www.eskimo.com/~scs/cclass/int/sx9b.html) –

4

請記住,數組衰減指針,可以用作指針。這些指針可以用作數組。實際上,索引一個數組可以被看作是一種形式或指針算術。例如

int a[3] = { 1, 2, 3 }; /* Define and initialize an array */ 
printf("a[1] = %d\n", a[1]); /* Use array indexing */ 
printf("*(a + 1) = %d\n", *(a + 1)); /* Use pointer arithmetic */ 

兩個輸出將上述陣列中打印第二(索引1)項。

指針的相同方式是真實的,它們可以用於指針算術,也可以用於數組索引。

從上面可以看出,認爲的pointer-to-pointer-to.type類型爲array-of-type。但這並非全部真相,因爲它們在內存中的存儲方式不同。所以你不能將一個數組數組作爲參數傳遞給一個需要指針指針的函數。但是,您可以在初始化它之後,像普通指針一樣使用指向數組索引的指針。

2

malloc的用於動態分配內存以的*測試變量看成是一個數組和作爲**數組的數組但不是由值傳遞的指針被用來引用該變量的存儲器地址。當調用malloc時,通過獲取整數的大小並乘以用戶提供的整數,將內存分配給測試變量,因爲在用戶輸入此內容之前,這是未知的。

2

是的,它非常好。 test是指向指針的指針,所以test[i]等於寫入test + i將是一個指針。爲了更好的理解,請看看這個​​。

2

確實是這樣,int**是一個指針的指針。我們也可以說這是一個指針數組。

test = (int **) malloc(k * sizeof(int*)); 

這將首先分配一個k指針數組。 malloc動態分配內存。

test[i] = (int*) malloc(k * sizeof(int)); 

這是沒有必要的,因爲它足以

test[i] = (int*) malloc(sizeof(int*)); 

在這裏,我們分配各自爲陣的地方指向一個有效的內存。但是對於像int這樣的基本類型,這種分配是沒有意義的。對於較大的類型(結構)它是有用的。

每個指針可以像陣列,並且反之亦然來訪問例如以下是等價的。

int a; 
test[i] = &a; 
(test + i) = &a; 

這可能是在存儲器陣列test被分配在開始偏移0x10000000的:

 
+------------+------------+ 
| OFFSET | POINTER | 
+------------+------------+ 
| 0x10000000 | 0x20000000 | test[0] 
+------------+------------+ 
| 0x10000004 | 0x30000000 | test[1] 
+------------+------------+ 
| ...  | ... 

每個元素(在本例0x2000000和0x30000000)是指向另一個分配的內存。

 
+------------+------------+ 
| OFFSET | VALUE | 
+------------+------------+ 
| 0x20000000 | 0x00000001 | *(test[0]) = 1 
+------------+------------+ 
| ... 
+------------+------------+ 
| 0x30000000 | 0x00000002 | *(test[1]) = 2 
+------------+------------+ 
| ... 

每個值僅包含sizeof(int)的空間。

在此示例中,test[0][0]將等於*(test[0]),但test[0][1]將無效,因爲它會訪問未分配的內存。

2

對於每個類型T,都存在一個「指向T的指針」類型。

通過*類型聲明符,可以將變量聲明爲指向各種類型值的指針。要將變量聲明爲指針,請在其名稱前加上星號。

因此,「對於每個類型T」也適用於指針類型,存在多個間接指針,如char **或int ***等。還存在着「指針數組」類型,但它們比「指針數組」較不常見(http://en.wikipedia.org/wiki/C_data_types

所以int**測試聲明指針數組指向爲「int陣列」

在線路test = (int **)malloc(k*sizeof(int*));把足夠的內存留出的k個量(int*)的

所以有k個量指針到,每個指向...

test[i] = (int*)malloc(k * sizeof(int));(每個指針指向與k的大小的數組金額)

摘要...

int** test;是由每個都指向到k的整數量指針的k個量。