【发布时间】: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 << ((a = --b) ? b : (b = -99)) << '\n';。 -
@chris 你是对的,
operator<<不会创建序列点,因此“a is”和“b is”部分可能在三元子句之前执行,但我相信这是实现-定义的行为,而不是未定义的行为。 -
@bcrist,不执行(如被打印),但可能被评估,是的。如果打印
a的那个在a被赋值之前被评估,UB,由于读取一个未初始化的变量。而如果打印b的那个在三进制之后求值,UB由于自上次修改b以来缺乏排序。但是,评估本身的顺序是未指定的,不是实现定义的行为。 -
@chris 实际上,再想一想,我相信这里没有歧义。因为
operator<<具有从左到右的关联性,所以像cout << a << b这样的东西会变成operator<<(operator<<(cout, a), b)。因此,a 保证在 b 之前被评估,因为逗号运算符触发了一个序列点 -
@bcrist,该表达式中没有逗号运算符。用于函数参数时不是运算符。
标签: c++ operator-keyword ternary