2014-02-20 87 views
3

根據C FAQ on instantiating a matrix using a double pointer的建議,我偶然發現了另一個問題。我設法解決了這個問題,但很難理解爲什麼它以一種方式而不是另一種方式工作。修改通過引用傳遞的變量與從函數返回的變量

我有下面的代碼的工作,然後我會告訴你不工作的位,我希望你能解釋一下爲什麼:

​​3210

分配網格內存和返回這種方式的指針工作。然而,我第一次嘗試另一種方式,我相信應該也可以使用,但它並不:

#include <stdio.h> 
#include <stdlib.h> 

int HEIGHT = 20; 
int WIDTH = 20; 

int ** curr_grid; 

/** 
* Generate an array with the given height and length 
*/ 
create_grid(int ** grid) { 
    grid = malloc(sizeof(int *) * HEIGHT); 
    int row; 
    for (row = 0; row < HEIGHT; row++) 
     grid[row] = malloc(sizeof(int) * WIDTH); 
} 

/* Entry Point main */ 
int main(int argc, char** argv) { 
    create_grid(curr_grid); 
    curr_grid[0][0] = 0; // Segmentation Fault 
    free(curr_grid); // Release heap resources 
    return 0; 
} 

這樣做,這樣與上標明的線路段故障。但是,我的印象是,通過引用傳遞變量允許您修改它。

爲什麼這不工作?

+0

函數內部的'grid'是從'main'傳入的參數的**副本** ... –

+1

您的標題顯示「通過引用傳遞」,但實際上並沒有這樣做。 –

+0

它可能會泄露我是一個完整的C新手。如果您對重命名該問題有任何想法,我將非常感激。 – mydoghasworms

回答

1

你想這樣的:

void create_grid(int ***grid) { 
    *grid = malloc(sizeof(int *) * HEIGHT); 
    int row; 
    for (row = 0; row < HEIGHT; row++) 
     (*grid)[row] = malloc(sizeof(int) * WIDTH); 
} 

/* Entry Point main */ 
int main(int argc, char** argv) { 
    create_grid(&curr_grid); 
    curr_grid[0][0] = 0; 
    free(curr_grid); // Release heap resources 
    return 0; 
} 

這就像下面的例子:

int MyFunction() 
{ 
    return 3 ; // we return directly 3 
} 

void main() 
{ 
    int a ; 
    a = MyFunction() ;  
} 

VS:

void MyFunction1(int *pa) 
{ 
    *pa = 3 ; // we assign 3 to the memory location pointed by pa 
} 

void main2() 
{ 
    int a ; 
    MyFunction1(&a) ; // we pass the pointer to a/
    // now a contains 3 
} 
+0

所以你說我必須傳遞一個指針指針?我認爲憑藉這個事實它是一個指針,它已經能夠修改內存中的空間了 – mydoghasworms

+0

是的如果你想通過一個void函數來修改一個int(像上面那樣),你必須傳遞一個指向'int'的指針,如果你想修改一個指向int的指針,你必須傳遞一個指向「int」的指針,依此類推。在你的情況下,你想修改一個指向int('int ** currgrid')的指針,因此你必須傳遞一個指針給一個指向指針的指針,如果是你想要的請接受我的答案 –

+0

我不確定是否接受你的答案或const。他提供了一個更好的解釋,但沒有用* **像你一樣。 – mydoghasworms

2

你不應該說create_grid(curr_grid); 這裏路過的指針的地址它傳遞curr_grid指針中存在的值(隨機值)並將您的價值轉化爲網格。一旦功能執行完成,它就從堆棧中取出。

嘗試傳遞您的指針的地址,然後將正常工作。

create_grid(&curr_grid);

編輯:查看以下鏈接希望它可以幫助你用圖形表示

Pointer tutorial

+0

我希望有一些圖形解釋,當這種情況發生時,解釋我對指針的理解有什麼問題。謝謝,現在我必須聽取您的意見,直到它滲入我厚厚的頭骨:-) – mydoghasworms

+0

我不確定是否接受您的答案或邁克爾的答案。他在函數中用***更好地展示了代碼,但是您提供了更好的解釋。 – mydoghasworms

0

的辦法知道如何通過任何類型的變量(指針或沒有,規則保持不變)是這樣的:

void create_grid(int **grid) { 
    grid = malloc(...); 
    ... 
} 

在這裏你傳遞一個名爲的變量並且您想要更改它的值grid = malloc(...);,但由於您僅使用grid而沒有任何*,因此您只有網格 的副本,並且對grids值所做的任何更改都不會在函數外可見。

在這種情況下

現在:

void create_grid(int ***grid) { 
    *grid = malloc(...); 
    ... 
} 

現在,當您訪問網格的價值利用和「*」,你知道,做這樣將保持在函數返回時,作爲網格實際上任何改變對二維數組的引用。

這很簡單,因爲它(不管是什麼類型的變量)。