C语言 在函数之间分配多个变量

gjmwrych  于 2023-03-17  发布在  其他
关注(0)|答案(2)|浏览(146)

我在写这个程序,在给一个函数赋值时遇到了麻烦,这是我思考的基础,但我尝试的时候,它似乎只取最后一个返回值。

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

这似乎只打印出“0 0 3”
我会错过什么呢?我确信它是函数中的return语句。只是出于好奇,我将return函数分隔为return var1... return var 3,结果是相同的,但这次打印“100”。所以我知道变量在那里,我只是不确定如何正确地分配它们。
基本上就是把x,y和z打印出来“123”

mrzz3bfm

mrzz3bfm1#

您似乎误解了,逗号运算符在C中的工作方式。在C中,逗号运算符的两个操作数都被求值,但运算的结果是右操作数的值。这意味着:
这条线

return var1, var2, var3;

相当于:

return var3;

这条线

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

相当于:

z = Function(x, y, z);

请注意,在行中

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

左边的x, y, z使用逗号操作符,如上所述,而右边的x, y, z不使用逗号操作符。,在这种情况下有完全不同的含义。它用作三个函数参数之间的分隔符。
如果你希望结果是1 2 3,那么我建议你通过指针传递变量到函数Function,如下所示:

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

或者,如果不想使用指针,也可以使用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;
}

另一种可能是使用数组:

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

x8diyxa72#

在启用警告的情况下编译代码会生成以下输出:

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.

遗憾的是,警告在默认情况下没有启用!
这意味着return var1, var2, var3;并不返回3个值,而是计算逗号运算符表达式var1, var2, var3,该表达式计算其最后一个操作数var3,并将此值3作为函数返回值返回。
类似地,x, y, z = Function(x, y, z);不实现3个值的并行存储,而是再次对逗号表达式求值,根据运算符优先规则,该逗号表达式被解析为:

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

xy计算为它们的值,这些值被忽略(但是如果它们被限定为volatile,则必须读取这些值),并且z = Function(x, y, z)最终将3存储到zyz被传递到Function,但没有被初始化,因此仅仅传递它们的值具有未定义的行为。
正如@AndreasWenzel所解释的,一个函数可以通过返回一个结构来返回多个值,或者通过指针更新调用范围中的值。
后者对于单独的变量更习惯:

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

输出:
对于描述同一对象的变量,将变量分组在结构中可能会更一致:

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

输出:

相关问题