How do I return multiple values from a function in C?

CReturn Value

C Problem Overview


If I have a function that produces a result int and a result string, how do I return them both from a function?

As far as I can tell I can only return one thing, as determined by the type preceding the function name.

C Solutions


Solution 1 - C

I don't know what your string is, but I'm going to assume that it manages its own memory.

You have two solutions:

1: Return a struct which contains all the types you need.

struct Tuple {
    int a;
    string b;
};

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

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

2: Use pointers to pass out values.

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);
}

Which one you choose to use depends largely on personal preference as to whatever semantics you like more.

Solution 2 - C

Option 1: Declare a struct with an int and string and return a struct variable.

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

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

Option 2: You can pass one of the two via pointer and make changes to the actual parameter through the pointer and return the other as usual:

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

or

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

Option 3: Similar to the option 2. You can pass both via pointer and return nothing from the function:

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

Solution 3 - C

Create a struct and set two values inside and return the struct variable.

struct result {
    int a;
    char *string;
}

You have to allocate space for the char * in your program.

Solution 4 - C

Since one of your result types is a string (and you're using C, not C++), I recommend passing pointers as output parameters. Use:

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

and call it like this:

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

In general, prefer to do the allocation in the calling function, not inside the function itself, so that you can be as open as possible for different allocation strategies.

Solution 5 - C

Two different approaches:

  1. Pass in your return values by pointer, and modify them inside the function. You declare your function as void, but it's returning via the values passed in as pointers.
  2. Define a struct that aggregates your return values.

I think that #1 is a little more obvious about what's going on, although it can get tedious if you have too many return values. In that case, option #2 works fairly well, although there's some mental overhead involved in making specialized structs for this purpose.

Solution 6 - C

Use pointers as your function parameters. Then use them to return multiple value.

Solution 7 - C

One approach is to use macros. Place this in a header file 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__)

This makes it possible to return up to four variables from a function and assign them to up to four variables. As an example, you can use them like this:

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;
}

This is what it prints:

(55, 3.9, 24.15)

The solution may not be as portable because it requires C99 or later for variadic macros and for-statement variable declarations. But I think it was interesting enough to post here. Another issue is that the compiler will not warn you if you assign them the wrong values, so you have to be careful.

Additional examples, and a stack-based version of the code using unions, are available at my github repository.

Solution 8 - C

By passing parameters by reference to function.

Examples:

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

Also by using global variables but it is not recommended.

Example:

int a=0;

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTony StarkView Question on Stackoverflow
Solution 1 - CTravis GockelView Answer on Stackoverflow
Solution 2 - CcodaddictView Answer on Stackoverflow
Solution 3 - Czs2020View Answer on Stackoverflow
Solution 4 - CJesse BederView Answer on Stackoverflow
Solution 5 - CJames ThompsonView Answer on Stackoverflow
Solution 6 - CBloodleeView Answer on Stackoverflow
Solution 7 - CKlas. SView Answer on Stackoverflow
Solution 8 - CBadrView Answer on Stackoverflow