如何从C中的函数返回多个值?

时间:2010-04-12 06:03:43

标签: c return-value

如果我有一个产生结果int和结果string的函数,我该如何从函数中返回它们?

据我所知,我只能返回一个东西,由函数名前面的类型决定。

8 个答案:

答案 0 :(得分:109)

我不知道你的string是什么,但我会假设它管理自己的记忆。

您有两种解决方案:

1:返回包含您需要的所有类型的struct

struct Tuple {
    int a;
    string b;
};

struct Tuple getPair() {
    Tuple r = { 1, getString() };
    return r;
}

void foo() {
    struct Tuple t = getPair();
}

2:使用指针传递值。

void getPair(int* a, string* b) {
    // Check that these are not pointing to NULL
    assert(a);
    assert(b);
    *a = 1;
    *b = getString();
}

void foo() {
    int a, b;
    getPair(&a, &b);
}

您选择使用哪一个在很大程度上取决于您喜欢的任何语义的个人偏好。

答案 1 :(得分:8)

Option 1:使用int和string声明一个struct并返回一个struct变量。

struct foo {    
 int bar1;
 char bar2[MAX];
};

struct foo fun() {
 struct foo fooObj;
 ...
 return fooObj;
}

Option 2:您可以传递两个via指针中的一个,并通过指针更改实际参数,并像往常一样返回另一个:

int fun(char **param) {
 int bar;
 ...
 strcpy(*param,"....");
 return bar;
}

 char* fun(int *param) {
 char *str = /* malloc suitably.*/
 ...
 strcpy(str,"....");
 *param = /* some value */
 return str;
}

Option 3:与选项2类似。您可以通过指针传递两者并从函数中返回任何内容:

void fun(char **param1,int *param2) {
 strcpy(*param1,"....");
 *param2 = /* some calculated value */
}

答案 2 :(得分:5)

创建一个struct并在其中设置两个值并返回struct变量。

struct result {
    int a;
    char *string;
}

您必须为程序中的char *分配空间。

答案 3 :(得分:5)

两种不同的方法:

  1. 通过指针传递返回值,并在函数内修改它们。您将函数声明为void,但它通过作为指针传入的值返回。
  2. 定义一个聚合返回值的结构。
  3. 我认为#1对于正在发生的事情更为明显,但如果你有太多的回报值,它会变得乏味。在这种情况下,选项#2工作得相当好,尽管为此目的制作专门的结构有一些精神上的开销。

答案 4 :(得分:5)

由于您的一个结果类型是一个字符串(并且您使用的是C而不是C ++),我建议将指针作为输出参数传递。使用:

void foo(int *a, char *s, int size);

并将其称为:

int a;
char *s = (char *)malloc(100); /* I never know how much to allocate :) */
foo(&a, s, 100);

一般情况下,更喜欢在调用函数中进行分配,而不是在函数本身内部进行分配,这样您就可以对不同的分配策略尽可能地开放。

答案 5 :(得分:2)

使用指针作为函数参数。 然后使用它们返回多个值。

答案 6 :(得分:1)

通过参考函数传递参数。

示例:

 void incInt(int *y)
 {
     (*y)++;  // Increase the value of 'x', in main, by one.
 }

同样通过使用全局变量,但不建议使用。

示例:

int a=0;

void main(void)
{
    //Anything you want to code.
}

答案 7 :(得分:1)

一种方法是使用宏。将其放在标题文件multitype.h

#include <stdlib.h>

/* ============================= HELPER MACROS ============================= */

/* __typeof__(V) abbreviation */

#define TOF(V) __typeof__(V)

/* Expand variables list to list of typeof and variable names */

#define TO3(_0,_1,_2,_3) TOF(_0) v0; TOF(_1) v1; TOF(_2) v2; TOF(_3) v3;
#define TO2(_0,_1,_2)    TOF(_0) v0; TOF(_1) v1; TOF(_2) v2;
#define TO1(_0,_1)       TOF(_0) v0; TOF(_1) v1;
#define TO0(_0)          TOF(_0) v0;

#define TO_(_0,_1,_2,_3,TO_MACRO,...) TO_MACRO

#define TO(...) TO_(__VA_ARGS__,TO3,TO2,TO1,TO0)(__VA_ARGS__)

/* Assign to multitype */

#define MTA3(_0,_1,_2,_3) _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2; _3 = mtr.v3;
#define MTA2(_0,_1,_2)    _0 = mtr.v0; _1 = mtr.v1; _2 = mtr.v2;
#define MTA1(_0,_1)       _0 = mtr.v0; _1 = mtr.v1;
#define MTA0(_0)          _0 = mtr.v0;

#define MTA_(_0,_1,_2,_3,MTA_MACRO,...) MTA_MACRO

#define MTA(...) MTA_(__VA_ARGS__,MTA3,MTA2,MTA1,MTA0)(__VA_ARGS__)

/* Return multitype if multiple arguments, return normally if only one */

#define MTR1(...) {                                                           \
    typedef struct mtr_s {                                                    \
      TO(__VA_ARGS__)                                                         \
    } mtr_t;                                                                  \
    mtr_t *mtr = malloc(sizeof(mtr_t));                                       \
    *mtr = (mtr_t){__VA_ARGS__};                                              \
    return mtr;                                                               \
  }

#define MTR0(_0) return(_0)

#define MTR_(_0,_1,_2,_3,MTR_MACRO,...) MTR_MACRO

/* ============================== API MACROS =============================== */

/* Declare return type before function */

typedef void* multitype;

#define multitype(...) multitype

/* Assign return values to variables */

#define let(...)                                                              \
  for(int mti = 0; !mti;)                                                     \
    for(multitype mt; mti < 2; mti++)                                         \
      if(mti) {                                                               \
        typedef struct mtr_s {                                                \
          TO(__VA_ARGS__)                                                     \
        } mtr_t;                                                              \
        mtr_t mtr = *(mtr_t*)mt;                                              \
        MTA(__VA_ARGS__)                                                      \
        free(mt);                                                             \
      } else                                                                  \
        mt

/* Return */

#define RETURN(...) MTR_(__VA_ARGS__,MTR1,MTR1,MTR1,MTR0)(__VA_ARGS__)

这样就可以从函数中返回最多四个变量,并将它们分配给最多四个变量。例如,您可以像这样使用它们:

multitype (int,float,double) fun() {
    int a = 55;
    float b = 3.9;
    double c = 24.15;

    RETURN (a,b,c);
}

int main(int argc, char *argv[]) {
    int x;
    float y;
    double z;

    let (x,y,z) = fun();

    printf("(%d, %f, %g\n)", x, y, z);

    return 0;
}

这就是它打印的内容:

(55, 3.9, 24.15)

该解决方案可能不具备可移植性,因为它需要C99或更高版本才能使用可变参数宏和for语句变量声明。但我觉得在这里发帖很有意思。另一个问题是如果你为它们分配错误的值,编译器不会警告你,所以你必须小心。

我的github repository提供了其他示例以及使用联合的基于堆栈的代码版本。

相关问题