?:运算符在C中如何工作?


10

我有一个问题,编译器如何对以下代码进行操作:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

我不知道为什么结果d = 11


1
你为什么不确定?您还会期望什么,为什么?
Gerhardh

2
我不记得所涉及的确切语义,但是您可能正在观察未定义的行为。
chepner

3
不,@ chepner,在评估三元条件之后,在评估所选替代方案之前,有一个序列点。这避免了我想您正在考虑的UB向量。
John Bollinger

是的,我不确定编译器在哪里可以选择。
chepner

Answers:


6

int d = (b == c++) ? (c+1) : (c-1);

  • 的值c++是的当前值c11。分别c增加到12。
  • b == 11是假的,因为b是12。
  • 由于(b == c++)为false,因此(c-1)被使用。同样,c到这一点,必须完成到12 的增量。
  • 因为c是12,所以c-1是11。
  • d 初始化为该值11。

5

根据C标准(6.5.15条件运算符)

4对第一个操作数求值;在它的评估与第二个或第三个操作数的评估(无论哪个被评估)之间都有一个序列点。仅当第一个操作数不等于0时,才对第二个操作数求值;仅当第一个操作数等于0时,才计算第三个操作数;结果是第二个或第三个操作数的值(以所评估的为准),转换为下面描述的类型。110)

因此,在此声明的初始化表达式中

int d = (b == c++) ? (c+1) : (c-1);

将变量b与变量的值进行比较,c因为后递增运算符在递增操作数之前会返回其操作数的值。

由于值彼此不相等(b设置为12,而c设置为11),因此将(c-1)评估子表达式。

根据报价,在评估操作员的状况之后会有一个顺序点。这意味着在对条件c求值12后,将后递增运算符应用于变量之后,该值便具有值c。结果,变量d由值112 - 1)初始化。


2
唯一正确的答案-这种特殊情况必须通过提及中的顺序点来回答?:。因为通常在C语言中,++与同一操作数上的其他操作合并是未定义的行为。此代码仅可预测地起作用,因为它们?:具有各种特殊的雪花规则。
伦丁

4

由于条件为假,因此false将发生这种情况:c-1,但是由于您c在条件中增加c++,因此c现在为12。因此,结果12-1为11。

编辑:OP误解了职位增量。

因此,实际发生的情况是这样的:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}

1
我认为,鉴于c++条件,OP指的是操作顺序。条件为假,但随后使用的原始c来计算c - 1,而不是增量版本。
chepner

1
我以为成功12 == 11 + 1是对的……
J0S

但是那不是真的,因为使用了新的c值,还是我错过了你的意思?
Eraklon

我认为c++和之间可能会有误解++c
ChatterOne

@ N00b c++递增运算符。的值为c++11,具有make的副作用c == 12++c将有12值
chepner

4

转换为常规的if语句,您的代码将如下所示:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

这里的线索是检查条件之后 c会增加。因此,您输入了else状态,但是c那里已经有值12。


1

请参阅三元运算符。

句法

健康)状况 ?value_if_true:value_if_false

所以,你写了

int d = (b == c++) ? (c+1) : (c-1);

在这种情况下,结果将为11,因为在进行检查之后,'c'的值增加了(c + 1 = 12),然后才将'd'的值设置为c(12)-1,即11。

例如,如果您使用过:

int d = (b == ++c) ? (c+1) : (c-1);

“ c”值将在检查该语句之前增加,因此它为true,而“ d”值将为c(12)+1,即13。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.