在三元运算中设置 2 个值 - C

set 2 values in a ternary operation - C

我在 C 中使用三元运算符设置两个整数时遇到问题。我似乎找不到答案,因为大多数问题都与多个三元条件有关。

然而,我想检查一个条件并相应地设置 2 个值。

即:

if ( i == 5 ) {
    x = foo;
    y = foo + 1;
} else {
    x = bar;
    y = bar + 1;
}

到目前为止,我尝试了以下方法,但它似乎不起作用。

x, y = ( i == 5 ) ? foo, foo + 1 : bar, bar + 1;

是否可以在检查1个条件后在三进制中设置两个值?

谢谢,

这是不可能的。与 python 或支持分配给数字列表的 perl 不同,C 不支持此语法。

您需要两个独立的三元运算来执行此操作:

x = (i == 5) ? foo : bar;
y = (i == 5) ? foo + 1 : bar + 1;

如果您只希望条件 运行 一次(例如,这是一个函数调用或其他一些昂贵的操作):

int result = (i == 5);
x = result ? foo : bar;
y = result ? foo + 1 : bar + 1;

编辑:

如果你想使用一些丑陋的东西,这会起作用:

x = (i == 5) ? (y = foo + 1, foo) : (y = bar + 1, bar);

通过使用逗号运算符,计算运算符的左侧(在这种情况下,对 y 的赋值)并丢弃,而右侧成为随后被分配给的表达式的值x.

请注意,"if" 部分并非严格需要括号,但 "else" 部分需要括号。

然而,这是对语言的滥用。最好坚持使用更具可读性的内容。

你可以使用一个函数:

void setAndIncrement(int val, int *x, int *y) {
    *x = val;
    *y = val + 1;
}

....

(i == 5) ? setAndIncrement(foo, &x, &y): setAndIncrement(bar, &x, &y);

但这不会使任何东西变得更好或更容易维护。你真的应该坚持使用 ifelse。它易于阅读、可维护,并且完全按照您应该做的方式进行。

正如@dbush 所说,您不能在 C 中执行此操作。在 C++ 中,您可以使用各种元组类型,但这超出了问题的范围。

为什么不呢?在 Python 和许多较新的语言中,逗号运算符将值(松散地说)捆绑在一起,因此可以将它们视为一个单元。这就是 Python 所做的,也是允许 x,y = 1,2 if a else 3,4 工作的原因。

然而,在 C 中,逗号运算符分隔 表达式 语句 ,而不是 . a,b 计算 a,丢弃结果,计算 b,并提供计算 b 的结果作为逗号的结果。 ab 绝不会一起考虑。

(C 向导和语言律师:为了 OP 的可读性,我故意省略 lvalue/rvalue 考虑因素和其他更精细的语义点。是的,你是正确的,完整的答案不应该这样做.:))

虽然我不建议为此使用单个三元运算,但可以做到。如果这只是一个挑战,这里有一些解决方案:

y = 1 + (i == 5 ? (x = foo) : (x = bar));

或者:

y = 1 + (x = i == 5 ? foo : bar);

或更一般的:

(i == 5) ? (x = foo, y = foo + 1) : (x = bar, y = bar + 1);

如您所见,所有这些都有些扭曲且可读性不强。

如果你能写2个语句,我会推荐:

x = (i == 5) ? foo : bar;
y = x + 1;

实现设置两个值的目标的各种方法:

当然第一个是干净易读的。

if ( i == 5 ) {
    x = foo;
    y = foo + 1;
} else {
    x = bar;
    y = bar + 1;
}

另一种是设置一个对象的 N 字段并使用 C11 复合文字 分配它。这适用于 ?:,因为代码正在设置一个对象。

  int i = rand(), foo = rand(), bar = rand();
  typedef struct {
    int x;
    int y;
    int z;
  } xyz_T;
  xyz_T xyz = (i == 5) ? 
      (xyz_T ) { .x = foo, .y = foo + 1, .z = 1 } : 
      (xyz_T ) { .x = bar, .y = bar + 1, .z = 2 };