2011-04-24 43 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