有效的多个返回值

时间:2014-01-03 20:15:21

标签: c function return multiple-variable-return

让我们假设我们的函数应该返回两个返回值。 例如,我们有一些函数返回char*及其长度。 Char在该特定函数内分配。

我可以想象以下方法:

int foo(char **result);       // Passing pointer to char*, returning int
char* bar(int *len);          // Passing pointer to int, returning char*
struct char_and_len foobar(); // Returning struct that contains both values

有没有其他方法可以实现多个值,最有效的方法是什么?

我非常感谢详细解释,考虑性能,内存对齐或任何其他隐藏的C功能。

7 个答案:

答案 0 :(得分:3)

这里有两种情况。如果您在代码库/框架(例如Glib)中工作,该代码库/框架具有在整个应用程序中使用的标准字符串结构,那么请使用您的第三个选项:

struct string function();

如果你的代码库没有为字符串使用一个标准结构,我建议不要使用结构。来回转换的麻烦并不值得。

否则,约定(至少我已经看过)是返回char*并将长度作为指针参数:

char* function(int* length);

答案 1 :(得分:1)

另一种方式:

void foo(char **result, int *len);

我认为最糟糕的是:

struct char_and_len foobar();

我更喜欢的是我向你展示的那个,因为我不喜欢在两个参数和有效回报中混合返回值。

答案 2 :(得分:1)

您只需返回一个数组并将其包装在struct:

typedef struct {
    char *strings[2];
} RetType;

RetType func()
{
    return (RetType){ { "foo", "bar" } };
}

另一个惯用的解决方案是C将一个数组传递给你的函数并填充它:

void func(char *strings[2])
{
    strings[0] = "foo";
    strings[1] = "bar";
}

第三个解决方案是返回一个值并通过指针传递另一个值(尽管如果你有不同类型的值,这更有意义):

char *func(char **outparm)
{
    *outparm = "foo";
    return "bar";
}

另外,请原谅我没有const - 正确。

答案 3 :(得分:1)

我最喜欢的是

void foobar(struct char_and_len*);

出于以下原因:

  • 只需要传递一个参数
  • 返回值/输出参数未混合
  • 返回值可以忽略,尤其是当需要再次释放返回值时,这可能是编程错误的严重来源。 Out参数不能忽略。
  • 拥有指向struct的指针可以避免过多的复制操作。只需要向函数提供一个指针。
  • 这样,函数的调用者可以决定struct char_and_len的存储位置(在堆,堆栈上),而在使用返回值时,数据需要至少暂时放在堆栈上

答案 4 :(得分:1)

使用字符串。

对于您引用的具体示例,请记住长度是隐式或显式的任何字符串类型的属性。例如,C风格的字符串以空值终止,因此即使没有明确的长度,调用者仍然可以确定字符串的长度。 Pascal样式的字符串包括长度作为第一个字节。 char*不一定是字符串,它可能是一个普通的旧文本缓冲区,其中需要长度。但字符串类型的要点是避免分别传递数据和长度的需要。

更一般......

一个函数只能返回一个值,所以如果你需要返回多个值,你需要使用struct将所有内容打包成一个值,或者传递指针(或指针)到一个接收结果的位置。您使用哪种方法取决于具体情况。您是否已经为需要返回的数据定义了结构?调用者是否可能拥有可以接收结果的现有对象?没有最佳方法,只有适当的方法。

答案 5 :(得分:0)

最好的方法是使用指针。在C中,每个函数都复制在不同内存区域中传递的参数。最好的方法是在性能方面发布的三个中的第二个。

但是我会传递一个指向结构的指针,该结构包含lenght和带有void返回的字符串。

答案 6 :(得分:0)

在C中,返回两个值并不“正常”。这意味着您已经创建了一个结构来返回结果。这是正式的正确做法,但不是最简单的方式,而且很有道理。所以我完全忘记了这个解决方案。

通常,返回结果的另一种方法是通过引用传递参数(在Pascal VB等中)。 在C中,没有可能通过引用传递它们而不是传递指针。 但是在C ++中,有可能通过引用传递变量(这仅仅意味着传递指针但使用变量)。

所以我相信做你需要的最简单的方法是定义:

char * bar(int * lenP); //

现在你得到一个可以返回两个结果的函数的结果:

就好像它被定义为伪语法(s,l)= bar();

此外,您还可以使用:

void bar(char * * s,int * lenP); //那个案子同样对待过多的论点。

在C ++中,我会使用by引用方法,因为从实际角度来看(处理器的作用)是相同的,对程序员来说更简单。