16

我对Java很熟悉,在C中不是这样。

在Java中,如果我有一个方法可以做某事并返回一个字符串,它看起来像:

private String doSomething(...) {
    String s;
    // do something;
    return s;
}

C 中的等效句法不起作用,而且是完全错误的:

char* doSomething(...) {
    char s[100];
    // do something;
    return s;
}

我当然可以:

char* doSomething(...) {
    char *s;
    s = malloc(100 * sizeof(char));
    // do something;
    return s;
}

这会起作用(我认为!)但我很少看到代码这样做(是因为它不必要地填充了堆?)

最常见的是,我看到:

bool doSomething(char *s) {
    // do something that copies chars to s
    return true;
}

调用语句将是:

char s[100];
doSomething(s);

如果在函数本身内部之前我不知道 char 数组的大小怎么办?即我将无法在函数外部声明 char 数组,然后将其传入。

处理这种情况的正确方法是什么?

4

5 回答 5

19

让调用代码负责分配内存。在示例 2 中传入缓冲区和缓冲区的长度:

bool doSomething(char *s, size_t buflen)
{ 
    // do something that copies chars to s up to max of buflen
    return true; 
} 

这往往会减少泄漏,因为调用代码控制着内存管理。

于 2011-11-29T13:02:26.097 回答
5

静态分配案例的示例(您必须在编译时考虑最大缓冲区大小)

buf[MAX_NO];
do(buf, MAX_NO);

_Bool do(char *s, size_t len) { 
// use len as boundary in your operations
}

或动态分配情况(如您所说使用 malloc 并使用指针来保存缓冲区位置和大小)

char *s = NULL;
size_t final_len;
do(&s, &final_len);

_Bool do(char** s, size_t* final_len) {
    size_t len = discoverSize();
    char* buf = (char*) malloc(sizeof(char) * len);

    *s = buf; //save memory location
    *final_len = len; //save buffer size
    // use len as boundary in your operations

}

// do whatever
free(s); //remember to free the buffer for politeness
于 2011-11-29T13:18:52.070 回答
2

当您无法知道返回字符串的正确大小时,请使用该malloc解决方案。当然,你必须在free完成之后使用字符串。

于 2011-11-29T13:03:44.990 回答
1

您不能在 C 中返回数组。

您可以返回一个指针,并且应该了解(通过阅读一本关于C语言编程的好书)数组和指针之间的区别。

一个常见的习惯用法是返回一个动态分配的指针。然后你应该有一个约定,告诉谁将释放指针。

您还可以返回包含数组的结构。

附加物

如果您想在 C 中使用垃圾收集器,请尝试Boehm 的垃圾收集器

于 2011-11-29T13:03:45.347 回答
0

最安全的方法是把分配的责任留给调用者,就像别人说的那样。

但是,如果您不需要 Java 的可重入代码和简单性,那么 C 中的等效语法是:

char* doSomething(...) {
    static char s[100];
    // do something;
    return s;
}
于 2011-11-29T13:11:26.137 回答