C++ 17排序:赋值左侧的后增量

Tho*_*eod 4 c++ operator-precedence assignment-operator c++17

C++ 17标准通过一条规则修改C++语言的操作顺序的定义,结果如下:

在每个简单赋值表达式E1 = E2和每个复合赋值表达式E1 @ = E2中,E2的每个值计算和副作用在E1的每个值计算和副作用之前被排序.

然而,在编译GCC 8.1下面的代码时,-std=c++17-Wall

int v[] { 0,1,2,3,4,5,6,7 };
int *p0 = &v[0];
*p0++ = *p0 + 1;
cout << "v[0]: " << v[0] << endl;
Run Code Online (Sandbox Code Playgroud)

我收到以下警告:

main.cpp:266:8: warning: operation on 'p0' may be undefined [-Wsequence-point]
     *p0++ = *p0 + 1;
      ~~^~
Run Code Online (Sandbox Code Playgroud)

输出是:

v[0]: 1

问题是:警告是错误的吗?

Bar*_*rry 8

问题是:警告是错误的吗?

这取决于.

从技术上讲,有问题的代码是明确定义的.右侧在C++ 17的左侧之前排序,而在它之前是不确定的顺序.并且gcc在v[0] == 1完成任务后正确编译代码.

然而,它也是不应该写的可怕代码,所以虽然警告的具体措辞是错误的,但警告的实际精神对我来说似乎很好.至少,我不打算提交有关它的错误报告,这似乎不值得开发人员有时间修复.因人而异.

  • 当然,“可怕的代码”通常在情人眼中。有人认为`A &amp;&amp; B || C &amp;&amp; D`是糟糕的代码,因为他们从未研究过形式逻辑,也没有隐式地“成长”,因为他们知道联结始终具有更高的优先级。其他人认为`(A &amp;&amp; B)|| (C &amp;&amp; D)`是糟糕的代码,因为括号的使用暗示了非标准的评估顺序。关键在于该表达式感觉像是糟糕的代码,因为数十年来的C ++编码(即UB)已经根深蒂固地养成了这种习惯。但是现在不是。因此,曾经糟糕的现在是优雅的语法。 (2认同)