Amit Vig
Amit Vig

Reputation: 185

return more than one parameter from a function in C

i have been trying to figure out ways where i can return more than one value from a function in C.

Say for instance i have the

int compute(int a, int b)
{
int c;
// do some computation on a,b,c
// return a,b,c
}

now i can return these values say in an array, and i was trying to do that and i then i realized that the array needs to be dynamic so it can be referenced in main() as well.

Another way could be that i create a structure and then just return the struct variable.

Is there any simple and robust way of doing this, other than the above work around ? i have to return about 25 different computation values which are independent of each other from a method, and i have a lot structs in my code already.

Thank you.

Upvotes: 0

Views: 5281

Answers (8)

Faisal Naseer
Faisal Naseer

Reputation: 4248

You can also return array using pointers here is the demonstration. http://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm

Upvotes: 0

Lindenk
Lindenk

Reputation: 502

No you cannot but another alternative solution that is more c++ish would be to create a struct then return that.

    struct RET_TYPE
    {
        int a;
        int b;
    };

    struct RET_TYPE foo()
    {
         ...

         return RET_TYPE();
    }

Upvotes: 0

huon
huon

Reputation: 102046

You can't easily return more than one variable like, for example, Python with return (a,b,c). However you can pass pointers that are set to the other "return values" or use a struct.

Out-of-place

If you want a function to actually return separate values and not modify its arguments, a simple way is to pass additional pointers (you could also use structs). e.g. this function will compute the sum and difference of a pair of numbers:

int add_sub(int a, int b, int* ret2) {
   if (ret2) *ret2 = a - b;
   return a + b;
}

The if (ret1) allows you to safely pass NULL as the pointer argument, so that you can ignore that return value. You use this like:

int add, sub;
add = add_sub(10, 3, &sub);
// add == 13, sub == 7

int just_add;
just_add = add_sub(15, 5, NULL);
// just_add == 20

(Note, this technique can lead to confusing behaviour if you pass the same argument twice, e.g. a = add_sub(a, b, &b) doesn't give you what want.)

In-place

If you want to modify the arguments to a function, you can just pass those as pointers. e.g. this function will increment both its arguments and then return their sum:

int increment_and_sum(int* a, int* b) {
     (*a)++;
     (*b)++;
     return a + b
}

Which you use like:

int a = 10, b = 3, sum;
sum = increment_and_sum(&a, &b);
// a == 11, b == 4, sum == 15

(Note that you can't use literals in increment_and_sum, that is, you can't do increment_and_sum(3, 4) or increment_and_sum(&3, &4).)

Upvotes: 6

blueshift
blueshift

Reputation: 6882

The normal way to do it is with pointer arguments. If you need to return variable numbers of things, you can use a pointer to data and a pointer to an integer "number of things". Another way to do it is pointer-to-pointer, and have your function allocate memory as needed. This makes the caller responsible for freeing it.

Example:

int make_numbers(int **numbers, int *count)
{
  /* work out how many numbers we want to generate */
  *count = howmany;
  *numbers = malloc(*count * sizeof(int));
  /* fill *numbers array here */
  return 0; /* success */
}

void caller(void)
{
  int *numbers;
  int count;
  if (0 == make_numbers(&numbers, &count)) {
    /* use the numbers */
    free(numbers);
  }
}

Upvotes: 2

Makoto
Makoto

Reputation: 106390

Technically speaking, a function only returns one value. Otherwise, it wouldn't be a function (remember mathematical functions? Same principle here.).

What you can do is:

  • Place them in a struct and return the struct, if the elements are related. Probably the easiest and clearest way to do this.
  • Place them in an array and return the array. About as easy as a struct, but it may not be as clear.
  • (Numerical values only) You can use a sort of self-designed map to get them into one integer (a = 100 * a, b = 10 * b, c = c).

Example involving arrays:

int* coords(int x, int y) {
    int *a = calloc(sizeof(int), 2);
    a[0] = x;
    a[1] = y;
    return a;
} 

int main() {

    int* vals = coords(47, -121);
    printf("vals = {%d, %d}\n", vals[0], vals[1]);
    return 0;
}

vals = {47, -121}

Upvotes: 1

Joop Eggen
Joop Eggen

Reputation: 109547

If you want no structs you can only pass by reference. Would need good documentation, maybe even declarative programming.

void compute(int& a, int& b, int& c) { ... }
void compute(int* a, int* b, int* c) { ... }

Upvotes: -1

Cliff Ribaudo
Cliff Ribaudo

Reputation: 9039

Not possible you have to pass pointers to variables and set them in your method. Like so:

void get_some_values()
{
    int a=0, b=0, c=0;
    compute(&a, &b, &c);

    // after call to compute a=1, b=2, c=3;
}

void compute(int *a, int *b, int c*)
{
    *a = 1;
    *b = 2;
    *c = 3;
}

Upvotes: 2

Adam Liss
Adam Liss

Reputation: 48280

If the values are all logically related, then it makes sense to put them into a structure. But if you're changing only a few values that aren't tightly coupled, you can pass them as pointers like this:

int swap(int *a, int *b) {
  int tmp;

  if (a == b) { // Pointers are equal, so there's nothing to do!
    return -1;  // Indicate the values haven't changed.
  }

  tmp = *a;
  *a = *b;
  *b = tmp;
  return 0;  // Indicate the swap was successful.
}

void main(...) {
  int first = 12;
  int second = 34;

  if (swap(&first, &second) == -1) {
    printf("Didn't swap: %d, %\n", first, second);
  } else {
    printf("Swapped: %d, %d\n", first, second);
  }
}

It's a fairly standard technique to put data into the function arguments, and have the function return a value to indicate success/failure, or some other condition.\

Upvotes: 5

Related Questions