Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 根据序列点的预增量与后增量_C++_C++14_Language Lawyer_Increment_Undefined Behavior - Fatal编程技术网

C++ 根据序列点的预增量与后增量

C++ 根据序列点的预增量与后增量,c++,c++14,language-lawyer,increment,undefined-behavior,C++,C++14,Language Lawyer,Increment,Undefined Behavior,在本文中,有一些定义良好和未定义表达式的示例。我对其中两个特别感兴趣: (6) i = i++ + 1; // Undefined Behaviour (7) i = ++i + 1; // Well-defined Behaviour 这意味着在序列点和定义良好/未指定/未定义的行为方面,增量前和增量后存在差异,但我不明白这种差异来自何处 在标准草案(N4618)中有一个代码示例([intro.execution],第18页) i=i+++1;//i的值递增 i=i+++i;//

在本文中,有一些定义良好和未定义表达式的示例。我对其中两个特别感兴趣:

(6) i = i++ + 1;    // Undefined Behaviour
(7) i = ++i + 1;    // Well-defined Behaviour
这意味着在序列点和定义良好/未指定/未定义的行为方面,增量前和增量后存在差异,但我不明白这种差异来自何处

在标准草案(N4618)中有一个代码示例([intro.execution],第18页)

i=i+++1;//i的值递增

i=i+++i;//行为未定义

据我所知,这意味着表达式
I=I+++1
应该得到很好的定义,变量
I
的值应该增加
1
。然而,MSVS 2015中运行的此代码将
i
增加
2

那么,表达式
i=i+++1
中会发生什么?它是定义良好的、未定义的、实现定义的还是未指定的行为?如原始答案所述,在序列点和UB方面,在这个表达式和类似表达式中,增量前和增量后有什么区别吗?为什么VisualStudio显示的行为不同于标准中编写的行为


请注意,我主要对现代C++(14/17)感兴趣。

< P> <强>表达式中的代码> i=I+++ 1 < <代码>中会发生什么?它是定义良好的、未定义的、实现定义的还是未指定的行为?

标准中给出了这个确切的例子,我们有多幸运

N4296 1.9.15[简介执行]

i=i+++1;//行为未定义

当然,我们也想知道为什么。以下标准报价似乎与此相关:

N4296 1.9.15[简介执行]

[…]运算符操作数的值计算按顺序排列 在计算运算符结果的值之前。[……]

这告诉我们,求和将发生在赋值之前(duh,否则它怎么知道赋值什么!),但它不能保证增量将发生在赋值之前或之后,现在我们陷入了困境

N4296 1.9.15[简介执行]

[…]如果标量对象上的副作用相对于 对同一标量对象或值计算的另一个副作用 使用同一标量对象的值,而它们不是 潜在并发(1.10),行为未定义。[……]

赋值运算符对
i
的值有副作用,这意味着我们对同一标量对象有两个副作用(另一个是由
i++
执行的赋值),未排序,未定义

为什么Visual Studio显示的行为与标准中的书面行为不同?

没有。标准说它是未定义的,这意味着它可以做任何事情,从你想要的到完全不同的事情,只是碰巧这是被编译器吐出来的行为

i=++i+1;//定义明确的行为

这意味着在序列点和定义良好/未指定/未定义的行为方面,预增量和后增量之间存在差异,但我不明白这种差异来自何处

我认为这篇文章在几个方面是不正确的。引用与他们相同的部分,强调我的:

C++11 1.9/15
函数的操作数的值计算 运算符在计算运算符结果的值之前排序。如果对标量有副作用 对象相对于同一标量对象上的另一个副作用或值计算未排序 使用同一标量对象的值,行为是未定义的

然后,赋值运算符:

C++11.5.17
在所有情况下,赋值都是在右操作数和左操作数的值计算之后、赋值表达式的值计算之前排序的

值得注意的是,值计算或左右操作数不按顺序排列。(这已在C11中明确说明),否则它的文本与C++11完全相同。)

意思是在表达式
i=++i+1
相对于左操作数
i
的值计算,
++i
的副作用是不排序的。因此,根据1.9/15,这是未定义的行为。而且UB与任务的副作用毫无关系

至于表达式
i=i+++1
的值计算不是问题。根据后缀++的性质,更新
i++
的副作用必须在整个表达式的值计算之后排序。据我所知,这是一种定义明确的行为

因此,应使用正确的文本

(6) i = i++ + 1;    // Well-defined Behaviour
(7) i = ++i + 1;    // Undefined Behaviour
显然,在C++11 1.9/15
i=i+++1;//中有一个不正确的例子该行为未定义
,已在本标准的后续版本中更正

注意:所有这些都与序列点措辞的变化没有丝毫关系


1) C116.5.16/3

更新的存储值的副作用 左操作数在左操作数和左操作数的值计算之后排序 右操作数操作数的求值是不排序的。


序列点在C++11之后就不存在了。我猜(没有什么可以支持它)