这段代码是否有未定义的行为,是或否,为什么?

问题描述 投票:0回答:3
int a = 0;
cout<<(a++, ++a, a++, ++a, a++)<<"\n";

我怀疑上面的代码不是未定义的行为,我想验证一下。

我知道下面的代码有UB:

int a = 0;
cout << a++ << " " << ++a << " " << a++ << "\n";
c++ undefined-behavior
3个回答
0
投票

第一个例子没有未定义的行为,因为它使用了内置的逗号运算符。内置逗号运算符保证左操作数在右操作数之前排序。这意味着左操作数的所有值计算和副作用发生在右操作数的所有值计算和副作用之前。例如,第一个

a
执行的从
a
的读取和对
a++
的写入都发生在第一个
a 执行的从 
a
 读取和对 
++a
 的写入之前
,等等。

第二个例子可以翻译成

operator<<((operator<<(cout.operator<<(a++), " ")).operator<<(a++), " ").operator<<(a++);

这里变得更加棘手,因为没有涉及逗号运算符。这里的逗号只是将函数参数彼此分开,但不会调用内置的逗号运算符。

但是,C++17 有一些规则可以帮助我们。在函数调用表达式中,函数表达式排在任何参数表达式之前(但是,无法保证参数的计算顺序)。这意味着整个第一部分,即

operator<<((operator<<(cout.operator<<(a++), " ")).operator<<(a++), " ").operator<<

在最后一个

a++
之前被评估,这是它的论点。在第一部分中,部分

(operator<<(cout.operator<<(a++), " ")).operator<<

在第二个

a++
之前被评估,这是它的论点。所以这意味着原始表达式中的第一个
a++
排在第二个之前,第二个排在第三个之前。行为定义明确。

但是,在 C++17 之前,三个

a++
unsequenced,这意味着它们的计算可以重叠。这意味着行为是未定义的。


-2
投票

不,没有任何未定义的行为。如果我们拿第一个代码片段

int a = 0;
cout<<(a++, ++a, a++, ++a, a++)<<"\n";

在第一个a++中,在转到第二个参数++a之前将a值增加到1。在第二个参数之后,值为 2。在第三个参数(即 a++)之后,该值将变为 3。然后转到第 4 个参数,首先将 a 的值增加到 4,然后将 a 的值设置为 4。在最后一个参数有一个

post increment and therefore first it will set the value of the a. That means set the value as 4. And after this line it will changes it's value to 5
。如果您需要检查波纹管代码。它将 a 的值输出为 5.

#include <iostream>

int main() {
    int a = 0;
    std::cout << (a++, ++a, a++, ++a, a++) << "\n"; // 4
    std::cout << a << "\n"; // 5
    return 0;
}

接下来的代码,就简单了。这里也没有任何未定义的行为。

int a = 0;
cout << a++ << " " << ++a << " " << a++ << "\n";

first a is 0. Then in next line it sets and print a value a and then after increment by 1. 因为它是后增量。因此第一名的价值将是

0
。打印 0 后,由于后递增,它会递增 1,在到达第二位后,第一个 ++ 将被满足并且必须在打印前递增 a 值。这就是为什么 1+1 = 2,在第二位它会变成 2。之后直到第三位没有任何增量。到达第三名后有一个后增量,因为它会先打印然后增加它的值。这就是为什么在最后一个地方它也将打印为 2。 输出是
0 2 2
这是正常的输出。


-3
投票

看这里。我已将答案视为正常答案。这个答案不是未定义的行为。

© www.soinside.com 2019 - 2024. All rights reserved.