2011-04-24 32 views
0

我以前問過這個問題:Experimenting with pointers of arrays in C關於傳遞指向函數的指針和修改函數中的現有數組,以便將數組「返回」到main()。我留下了一個問題,這兩個代碼塊有什麼區別?用C返回數組,不同的方法

// #includes 

int ***myfunc(int***); 

int main() 
{ 
    int a***; 
    //allocate memory for array 'a' 
    a = myfunc(a); 

    // display all contents of array 'a' 

    return 0; 
} 

OR

// #includes 

void myfunc(int***); 

int main() 
{ 
    int a***; 
    //allocate memory for array 'a' 
    myfunc(a); 

    // display all contents of array 'a' 

    return 0; 
} 

兩種功能將修改陣列和當displaying all contents of a,其內容將是相同的。

我希望這不會造成混淆,我想我可以在需要的時候闡述更多。

一個顯著EDITTTTTTTTT

下面是兩個工作示例(據我所知):

#include "stdlib.h" 
#include "stdio.h" 


void myfunc(int**); 

int main() { 

    int **a,i, j; 

    a = (int**) calloc(10,sizeof(int*)); 
    for (i=0; i<10; i++) 
    a[i] = (int*) calloc(10, sizeof(int)); 

    myfunc(a); 

    for (i=0; i<10; i++) { 
    for (j=0; j<10; j++) 
     printf("%d ",a[i][j]); 
    printf("\n"); 
    } 

    return 0; 
} 


void myfunc(int** a) { 

    int i, j; 
    for (i=0; i<10; i++) 
    for (j=0; j<10; j++) 
     a[i][j] = i*j; 

} 

AND ...

#include "stdlib.h" 
#include "stdio.h" 

// returning arrays through functions 

int **myfunc(int **b); 

int main() { 

    int **a,i,j; 

    a = (int**) calloc(10,sizeof(int*)); 
    for (i=0; i<10; i++) 
    a[i] = (int*) calloc(10, sizeof(int)); 

    a = myfunc(a); 

    for (i=0; i<10; i++) { 
    for (j=0; j<10; j++) 
     printf("%d ",a[i][j]); 
    printf("\n"); 
    } 

    return 0; 
} 


int **myfunc(int **b) { 

    int i, j; 
    for (i=0; i<10; i++) 
    for (j=0; j<10; j++) 
     b[i][j] = i*j; 

    return b; 
} 
+0

在那裏做了那麼多「***」? – 2011-04-24 15:40:25

+0

我認爲不同的是,在第一個版本中,至少可以保存一個'*'。如果您認爲需要指向指針的指針,則可能需要重新考慮問題。 – 2011-04-24 15:45:44

+0

3d數組。我們可以將它用於所有密集型目的 – Amit 2011-04-24 15:45:54

回答

3

第二個功能無法修改你傳遞給它的指針(int***),但是當你做一個分配時,你會得到一個新的內存地址。這個新地址將被分配到myfunc之內的指針的本地副本,但它永遠不會達到main

這樣做的結果是,你會:

  • 使用內部main
  • 無效指針泄漏內部myfunc分配的內存。

可以採取的一個指針的指針緩解這種(哇!):

// #includes 

void myfunc(int****); 

int main() 
{ 
    int ***a; // <-- note: you had a typo here, originally! 

    //allocate memory for array 'a' 
    myfunc(&a); // <-- pass pointer by pointer 

    // display all contents of array 'a' 

    return 0; 
} 

,並確保myfunc是聰明瞭。

上面的代碼可以由更清晰一點與typedef

// #includes 
typedef int*** Ptr; 

void myfunc(Ptr*); 

int main() 
{ 
    Ptr a; 

    //allocate memory for array 'a' 
    myfunc(&a); // <-- pass pointer by pointer 

    // display all contents of array 'a' 

    return 0; 
} 

而且,你的第一種方法是更乾淨,並避免任何需要這種無稽之談。它只是返回指針的新值,然後您可以隨意指定和使用它。


編輯

我的理解是,內存分配在myfunc完成(響應顯著問題編輯);我現在看到情況並非如此。因此,您可以使用您列出的兩種方法(或上述第三種方法)中的任何一種;坦率地說,我不明白你爲什麼要打擾第一個,因爲你不會修改myfunc內的指針。

+0

我明白了。但是,我已經使用了第二種方法,並且都適用。你是否說有時會發生內存泄漏,並且第一種方法更安全? – Amit 2011-04-24 16:07:16

+0

@Amit:我看不出第二個人可以工作。除非我錯過了一些東西,否則你會調用未定義的行爲並使用實際上不屬於你的內存。如果它看起來「有效」,那就是運氣不好;它可能會隨時崩潰或導致其他內存損壞症狀。 – 2011-04-24 16:09:42

+0

讓我發表工作實例 – Amit 2011-04-24 16:30:57

0

你要修改的a價值,所以你必須通過一個指向它,而不是本身的價值:如果你想返回一個指向你分配的東西以及

myfunc(&a); // as opposed to myfunc(a); 

修改輸入參數,然後你會使用一個間接較少水平的返回類型:

int **myfunc(int ***a) { ... } 

所以在主要的調用看起來像

int **a, **b; 

b = myfunc(&a); 
+1

他的基本指針類型是'int ***'。如果他想通過指針傳遞指針,那麼就會變成'int ****'。 – 2011-04-24 16:10:50

+0

+1 @Tomalak有人設法在這個問題上工作'int ****'只是個時間問題! – 2011-04-24 16:30:46

+0

@David:那麼我希望你喜歡我的回答。 :) – 2011-04-24 16:31:45