在我正在处理的遗留代码库中,我发现了一行
n = ++n % size;
这只是对预期
的错误措辞n = (n+1) % size;
从周围的代码和运行时证明推导出来。 (后者现在取代了前者。)
但是由于这个代码被Cppckeck标记为错误,并且在GCC中引起了警告,没有造成任何故障,我并没有停止在这里思考。我将线路缩小为
n = ++n;
仍然收到原始错误/警告消息:
Cppcheck 1.80:
Id:unknownEvaluationOrder
摘要:表达式'n = ++ n'取决于副作用评估的顺序 消息:表达式'n = ++ n'取决于副作用评估的顺序
GCC(mingw32-g ++。exe,版本4.9.2,C ++ 98):
警告:'n'上的操作可能未定义[-Wsequence-point] |
我已经学会了assignment expressions in C/C++ can be heavily affected by undefined evaluation order,但在这种情况下我无法想象。
n = ++n;
的未定义评估顺序是否真的与生成的程序相关,尤其是n
的预期值?这就是我想象的可能发生的事情。
Scenario #1
++n;
n=n;
Scenario #2
n=n;
++n;
我知道继承undefined behaviour in C++的意义和含义很难理解,也难以教导。
我知道在C ++ 11之前,C ++标准未定义n=++n;
的行为。但它有一个来自C ++ 11的定义行为,这个(现在是标准定义的行为)与我正在观察的几个编译器 [1] 完全相同的这个小型演示程序
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cout << "n before: " << n << endl;
n=++n;
cout << "n after: " << n << endl;
return 0;
}
有输出
n before: 0
n after: 1
对于所有编译器而言,无论是否按标准定义,行为实际上都是相同的,这是否合理?你可以(a)显示一个反例或(b)给出一个易于理解的解释这个代码怎么样会产生错误的结果吗?
[1] 使用的编译器
答案 0 :(得分:3)
精确定义了increment order。在那里声明
i = ++i + 2; // undefined behavior until C++11
由于您使用的是C ++ 11编译器,因此可以按原样保留代码。不过,我认为
的表现力n = (n+1) % size;
更高。您可以更轻松地找出此代码的作者的意图。
答案 1 :(得分:-1)
根据cppreference:
如果相对于同一标量对象的另一个副作用,标量对象的副作用未被排序,则行为未定义:
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
对于案例n = ++n;
,这将是一个未定义的行为,但我们不关心哪个分配首先发生,n =
或++n
。