2

So I'm working on this program and seem to be having trouble assigning variables from 1 function to another, this is the basis of what I am thinking but it seems to only take the last returned value when I try.

#include <stdio.h>

int Function(int a, int b, int c) 
{
    int var1 = 1;
    int var2 = 2;
    int var3 = 3;
    
    return var1, var2, var3;
}

int main()
{
    int x, y, z;
    
    x, y, z = Function(x, y, z);

    printf("%d %d %d", x, y, z);
    
    return 0;
}

This seems to only print out "0 0 3"

What could I be missing? I'm sure its the return statement in the Function. Just out of curiosity I separated the return function to return var1... return var 3 in separate lines and the result is the same but this time prints "1 0 0". So I know the variables are there, I'm just not sure on how to assign them properly.

Basically just trying to get x, y and z to print out "1 2 3"

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39

2 Answers2

4

You seem to misunderstand how the , comma operator works in C. In C, both operands of the comma operator are evaluated, but the result of the operation is the value of the right operand. This means the following:

The line

return var1, var2, var3;

is equivalent to:

return var3;

The line

x, y, z = Function(x, y, z);

is equivalent to:

z = Function(x, y, z);

Note that in the line

x, y, z = Function(x, y, z);

the left x, y, z uses the comma operator, as described above, but the right x, y, z does not use the comma operator. The , has a completely different meaning in this case. It serves as a delimiter between the three function arguments.

If you want the result to be 1 2 3, then I suggest that you pass the variables by pointer to the function Function, like this:

#include <stdio.h>

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

int main(void)
{
    int x, y, z;
    
    Function(&x, &y, &z);

    printf("%d %d %d", x, y, z);
    
    return 0;
}

Alternatively, if you don't want to use pointers, you can also use a struct:

#include <stdio.h>

struct triplet
{
    int a;
    int b;
    int c;
};

struct triplet Function( void )
{
    return (struct triplet){1,2,3};
}

int main( void )
{
    struct triplet t;
    
    t = Function();

    printf("%d %d %d", t.a, t.b, t.c);
    
    return 0;
}

Another possibility is to use an array:

#include <stdio.h>

void Function( int arr[3] ) 
{
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
}

int main(void)
{
    int numbers[3];
    
    Function( numbers );

    printf("%d %d %d", numbers[0], numbers[1], numbers[2]);
    
    return 0;
}
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
1

Compiling your code with warnings enabled produces this output:

chqrlie> clang -Wall -Werror 230312-triplet.c
230312-triplet.c:9:12: error: left operand of comma operator has no effect
      [-Werror,-Wunused-value]
    return var1, var2, var3;
           ^~~~
230312-triplet.c:9:18: error: left operand of comma operator has no effect
      [-Werror,-Wunused-value]
    return var1, var2, var3;
                 ^~~~
230312-triplet.c:16:5: error: left operand of comma operator has no effect
      [-Werror,-Wunused-value]
    x, y, z = Function(x, y, z);
    ^
230312-triplet.c:16:8: error: left operand of comma operator has no effect
      [-Werror,-Wunused-value]
    x, y, z = Function(x, y, z);
       ^
230312-triplet.c:16:24: error: variable 'x' is uninitialized when used here
      [-Werror,-Wuninitialized]
    x, y, z = Function(x, y, z);
                       ^
230312-triplet.c:14:10: note: initialize the variable 'x' to silence this warning
    int x, y, z;
         ^
          = 0
230312-triplet.c:16:27: error: variable 'y' is uninitialized when used here
      [-Werror,-Wuninitialized]
    x, y, z = Function(x, y, z);
                          ^
230312-triplet.c:14:13: note: initialize the variable 'y' to silence this warning
    int x, y, z;
            ^
             = 0
230312-triplet.c:16:30: error: variable 'z' is uninitialized when used here
      [-Werror,-Wuninitialized]
    x, y, z = Function(x, y, z);
                             ^
230312-triplet.c:14:16: note: initialize the variable 'z' to silence this warning
    int x, y, z;
               ^
                = 0
7 errors generated.

It is a pity warnings are not enabled by default!

What this means is return var1, var2, var3; does not return 3 values, but evaluates the comma operator expression var1, var2, var3, which evaluates to its last operand var3, and returns this value 3 as the function return value.

Similarly, x, y, z = Function(x, y, z); does not implement parallel stores of the 3 values, but again evaluates a comma expression which according to the operator precedence rules is parsed as:

x, y, (z = Function(x, y, z));

x and y evaluate to their values which are ignored (but would have to be read were they qualified as volatile, and z = Function(x, y, z) finally stores 3 to z. Note also that x, y and z are passed to Function but are not initialized so merely passing their values has undefined behavior.

As explained by @AndreasWenzel, a function can return multiple values by returning a structure, or updating values in the calling scope via pointers.

The latter is more idiomatic for separate variables:

#include <stdio.h>

void intialize(int *a, int *b, int *c) {
    int var1 = 1;
    int var2 = 2;
    int var3 = 3;
    
    *a = var1;
    *b = var2;
    *c = var3;
}

int main() {
    int x, y, z;
    
    initialize(&x, &y, &z);

    printf("%d %d %d\n", x, y, z);
    
    return 0;
}

Output:

1 2 3

Grouping the variables in a structure may be more consistent for variables describing the same object:

#include <stdio.h>

typedef struct object {
   int x, y, y;
} object;

void object_initialize(object *obj) {
    obj->x = 1;
    obj->y = 2;
    obj->z = 3;
}

int main() {
    object o;
    
    object_initialize(&o);

    printf("%d %d %d\n", o.x, o.y, o.z);
    
    return 0;
}

Output:

1 2 3
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    For further reading about compiler warnings: [Why should I always enable compiler warnings?](https://stackoverflow.com/q/57842756/12149471) Thae answers of that question also explain how to enable all warnings. – Andreas Wenzel Mar 12 '23 at 14:04