为什么要始终按预期工作的UB更改UB
Why change UB that will always work as intended?
在我正在处理的旧代码库中,我发现了行
n = ++n % size;
这只是预期
的不良措辞n = (n+1) % size;
从周围的代码和运行时推论得出。(后者现在取代了前者。)
但是,由于此代码被CPPCKECK标记为错误,并在GCC中引起了警告,而没有引起任何故障,所以我并没有停止在这里思考。我将线路减少到
n = ++n;
仍然获取原始错误/警告消息:
cppcheck 1.80:
id:未知词
摘要:表达'n = n'取决于评估副作用的顺序
消息:表达式'n = n'取决于副作用评估顺序
GCC(Mingw32-G 。EXE,版本4.9.2,C 98):
警告:在'n'上操作可能是未定义的[-WSequence-point] |
我已经了解到,C/C 中的分配表达式可能会受到未定义的评估顺序的影响,但是在这种情况下,我无法想象。
n = ++n;
的不确定的评估顺序是否确实与结果程序相关,尤其是对于n
的预期值?这就是我想象的可能发生的事情。
Scenario #1
++n;
n=n;
Scenario #2
n=n;
++n;
我知道,对C 中不确定行为的含义和含义很难理解,也很难教导。
我知道n=++n;
的行为是在C 11之前由C 标准不确定的。但是它具有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)给出易于理解的 dixplantion 该代码如何会产生错误的结果吗?
[1] 编译器已使用的
- Borland-C 5.3.0(Pre-C 98)
- Borland-C 5.6.4(C 98)
- C (VC )
- C (GCC 6.3)
- C 14(GCC 6.3)
- C 14 clang
精确定义了增量顺序。有人说
i = ++i + 2; // undefined behavior until C++11
由于您使用C 11编译器,因此可以按原样保留代码。但是,我认为
的表现力n = (n+1) % size;
更高。您可以更轻松地弄清此代码作者的意图。
根据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
。
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 链表c++插入,所有情况都已检查,但没有任何工作
- 为什么要始终按预期工作的UB更改UB