4

我不是 C 方面的专家,但这是我正在尝试做的事情:

int main(void) {
    double *myArray;
    ...
    myFunction(myArray);
    ...
    /* save myArray contents to file */
    ...
    free(myArray);
    ...
    return 0;
}

int myFunction(double *myArray) {
    int len=0;
    ...
    /* compute len */
    ...
    myArray = malloc( sizeof(double) * len );
    if (myArray == NULL) 
      exit(1);
    ...
    /* populate myArray */
    ...
    return 0;
}

我想保存myArrayinside的内容main,但在程序进入 inside 之前我不知道所需的大小myFunction

由于我使用的是 CentOS 6.2 Linux,因此我只能找到最高 4.4.6 的 gcc 构建(它不支持声明可变长度数组的 C99 功能;请参阅“可变长度数组”下的“损坏” http://gcc.gnu.org/gcc-4.4/c99status.html),我被困-std=c89在编译。

4

4 回答 4

3

简单的答案是否定的。

您没有传回指针。

利用

int main(void) {
    double *myArray;
    ...
    myFunction(&myArray);
    ...
    /* save myArray contents to file */
    ...
    free(myArray);
    ...
    return 0;
}

int myFunction(double **myArray) {
    int len=0;
    ...
    /* compute len */
    ...
    *myArray = malloc( sizeof(double) * len );
    if (NULL == *myArray) 
      exit(1);
    ...

编辑

    poputateThis = *myArray;

    /* populate poputateThis */

编辑结束

    ...
    return 0;

编辑

应该为您简化 }

于 2012-11-19T18:45:08.303 回答
2

您正在做的事情不好,因为myFunction不会更改myArraymain 中的值;它只是更改自己的副本。

除此之外,即使在风格上值得商榷,也没关系。

于 2012-11-19T18:43:14.840 回答
2

作为良好设计和实践的问题(除了其他答案中指出的语法问题),只要它与您的代码库的最佳实践一致并且透明,就可以了。您的函数应该记录在案,以便调用者知道它必须释放并且知道不分配自己的内存。此外,考虑制作一个抽象数据类型,例如:

// myarray.h
   struct myarray_t;
   int myarray_init(myarray_t* array); //int for return code
   int myarray_cleanup(myarray_t* array); // will clean up

myarray_t将保存一个动态指针,该指针将从调用函数中封装,尽管在initcleanup函数中它将分别分配和释放。

于 2012-11-19T18:47:50.787 回答
1

你想做的很好,但你的代码没有这样做——main永远不会看到分配的内存。的参数使用函数调用中传递myArraymyFunction值进行初始化,但此后修改它不会修改main.

它出现在您myFunction始终返回的代码片段中0。如果是这样,那么修复代码的最明显方法是返回myArray(并且不带参数)。然后调用main看起来像myArray = myFunction();

如果myFunction实际上已经使用了它的返回值,那么您可以传入一个指向 的指针double*并将地址写入该指针的引用。这就是 Ed Heal 的回答。该double **参数通常称为“out-param”,因为它是指向函数用于存储其输出的位置的指针。在这种情况下,输出是缓冲区的地址。

另一种方法是做这样的事情:

size_t myFunction(double *myArray, size_t buf_len) {
    int len=0;
    ...
    /* compute len */
    ...
    if (buf_len < len) {
        return len;
    }
    /* populate myArray */
    ...
    return len;
}

然后调用者可以自由地以任何他们喜欢的方式分配内存。典型的调用代码可能如下所示:

size_t len = myFunction(NULL, 0);
// warning -- watch the case where len == 0, if that is possible
double *myArray = malloc(len * sizeof(*myArray));
if (!myArray) exit(1);
myFunction(myArray, len);
...
free(myArray);

您获得的是调用者可以从任何方便的地方分配内存。您失去的是调用者必须编写更多代码。

对于如何使用这种自由的示例,调用者可以写:

#define SMALLSIZE 10;

void one_of_several_jobs() {
    // doesn't usually require much space, occasionally does
    double smallbuf[SMALLSIZE];
    double *buf = 0;

    size_t len = myFunction(smallbuf, SMALLSIZE);
    if (len > SMALLSIZE) {
        double *buf = malloc(len * sizeof(*buf));
        if (!buf) {
            puts("this job is too big, skipping it and moving to the next one");
            return;
        }
    } else {
        buf = smallbuf;
    }

    // use buf and len for something
    ...

    if (buf != smallbuf) free(buf);
}

这通常是一种不必要的优化,以避免malloc在只需要一个小缓冲区的常见情况下进行 - 这只是调用者可能想要对如何分配内存有发言权的一个例子。一个更紧迫的原因可能是您的函数被编译成与调用者函数不同的 dll,可能使用不同的编译器,并且两者不使用兼容的malloc/free.

于 2012-11-19T18:49:48.587 回答