【问题标题】:What's the Right Way to Write a C Function Returning a char array?编写返回 char 数组的 C 函数的正确方法是什么?
【发布时间】:2012-01-08 19:32:56
【问题描述】:

我对 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 数组,然后将其传入。

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

【问题讨论】:

    标签: c string dynamic-allocation


    【解决方案1】:

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

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

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

    【讨论】:

    • 将数组传递给函数的最好之处在于它避免了耦合分配和内部逻辑(这很重要,因为 C 具有手动内存管理和多种分配数组的方法)
    • 我明白你的意思,也可以在代码中看到这个成语。但在我的场景中的问题是,在调用函数之前,我不会事先知道要分配的内存量和要传入的 buflen 的值。
    • 在这个答案中,函数被绑定到一个最大长度来操作。除非使用动态分配,否则无法避免此问题。
    • 调用代码可以动态分配和传入长度。
    【解决方案2】:

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

    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
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        你不能在 C 中返回一个数组。

        你可以返回一个指针,你应该学习(通过阅读一本关于C语言编程的好)数组之间的区别和指针。

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

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

        附录

        如果您想在 C 中使用垃圾收集器,请尝试 Boehm's garbage collector

        【讨论】:

          【解决方案5】:

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

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

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

          【讨论】:

          • 这在任何意义上都不是 Java 函数的语法工作等价物。 Java函数中的String不是静态对象,可以多次调用Java函数而不会踩到值。
          • @JeremyP - 我部分同意:这在语义上不等效。
          猜你喜欢
          • 1970-01-01
          • 2017-04-20
          • 2011-04-26
          • 2016-11-05
          • 2022-01-14
          • 2015-03-03
          • 1970-01-01
          • 2021-10-30
          • 2012-10-23
          相关资源
          最近更新 更多