【问题标题】:C++ ternary operator confusionC++ 三元运算符混淆
【发布时间】:2014-02-08 02:16:34
【问题描述】:

我有以下程序,除了我以外的每个人都应该很简单!

#include <iostream>
using namespace std;
int main()
{

int a, b;
b = 1;

cout << ((a = --b) ? b : (b = -99)) << '\n' << "a is " << a << '\n' << "b is " << b << endl;

b = 1;
cout << (a = --b ? b : (b = -99)) << '\n' << "a is " << a << '\n' << "b is " << b << endl;


}

程序的输出是:

-99

a 为 0

b 是 -99

-99

a 是 -99

b 是 -99

在第一段代码中,我理解的是,a 被赋予值--b, 0,因此它变为 false,因此执行 b=-99。我无法理解第二段代码,其中 a=--b 没有括号,为什么 a 的值是 -99。

【问题讨论】:

  • b 设置为-99,然后像这样打印它应该会导致未定义的行为AFAIK。此外,每个输出表达式的求值顺序是未指定的,这会导致更多问题。基本上,如果我是对的,这里唯一有风险但安全的事情就是单个 cout &lt;&lt; ((a = --b) ? b : (b = -99)) &lt;&lt; '\n';
  • @chris 你是对的,operator&lt;&lt; 不会创建序列点,因此“a is”和“b is”部分可能在三元子句之前执行,但我相信这是实现-定义的行为,而不是未定义的行为。
  • @bcrist,不执行(如被打印),但可能被评估,是的。如果打印a 的那个在a 被赋值之前被评估,UB,由于读取一个未初始化的变量。而如果打印b的那个在三进制之后求值,UB由于自上次修改b以来缺乏排序。但是,评估本身的顺序是未指定的,不是实现定义的行为。
  • @chris 实际上,再想一想,我相信这里没有歧义。因为operator&lt;&lt; 具有从左到右的关联性,所以像cout &lt;&lt; a &lt;&lt; b 这样的东西会变成operator&lt;&lt;(operator&lt;&lt;(cout, a), b)。因此,a 保证在 b 之前被评估,因为逗号运算符触发了一个序列点
  • @bcrist,该表达式中没有逗号运算符。用于函数参数时不是运算符。

标签: c++ operator-keyword ternary


【解决方案1】:
(a = --b ? b : (b = -99))

这里,因为=?the same priority(根据提供的链接是15个)并且从右到左求值,所以执行如下:

a = --b ? b : (b = -99)
1. --b ( =0)
2. 0?
3. 0 so not what is immediately after ? but what is after :
4. b=-99 (evaluate second expression)
5. a = -99 (assign the result of expression)

【讨论】:

  • ; ) 完美,我很高兴有帮助
【解决方案2】:

三元运算符具有从右到左的结合性,并且与赋值具有相同的优先级,这意味着第二段的条件项被解释为 a = ( --b ? b : (b = -99))

【讨论】:

  • 谢谢,括号确实有影响
【解决方案3】:

这是因为=?: (C++ operator priorities) 具有相同的优先级。在这种情况下,由于它们具有从右到左的关联性,因此它们的求值是从右到左的。因此,首先将表达式 --b ? b : (b = -99) 计算为 -99,然后将其分配给 a

【讨论】:

  • 我一定会再次检查优先级,似乎需要更好地了解它们。不过感谢您的提醒。
猜你喜欢
  • 2021-12-30
  • 2012-02-13
  • 2020-10-25
  • 2012-03-09
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 1970-01-01
  • 2013-07-05
相关资源
最近更新 更多