前缀(++ x)和后缀(x ++)操作如何工作?

God*_*ene 26 c c# c++ sequence-points

有人能告诉我前缀/后缀运算符是如何工作的吗?我一直在网上看很多但没找到任何东西.

从我可以告诉prefex第一个增量,然后执行操作,然后分配.
Postfix将首先执行操作,然后分配然后递增.

但是我的代码遇到了一些麻烦:

int x, y;
x = 1;
y = x + x++; // (After operation y = 2)(x=2)
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时:

y = x++ + x; // (After operation y = 3)(x=2)
Run Code Online (Sandbox Code Playgroud)

我不确定为什么这些操作会有所不同.我有两个问题:

  • 你能解释一下这个区别吗?

  • 这如何适用于其他运营商Prefix?

Eri*_*ert 60

这个问题得到了相当多的要求.请注意,每当有人问这个问题时,很多人都会发布错误的答案.很多人对这些操作员的工作方式有不正确的想法,包括编写编程书籍的人,从而教导其他人的谎言.请仔细阅读其他答案.

有关C#行为的正确分析,请参阅:

i ++和++ i有什么区别?

对于C++,在您观察副作用的情况下,任何行为都是正确的行为.C++没有定义增量的副作用何时可见.任何两个编译器都可以采用不同的方式.

遵循的一个好规则是不依赖于任何语言中副作用发生的顺序,但在C++中肯定不依赖它,因为它不可靠.

看看你的具体情况:

int x, y;     
x = 1;     
y = x + x++; 
Run Code Online (Sandbox Code Playgroud)

您报告x和y都是2.这在C#中是正确的.在C#中,正确的行为是:

  • 将y评估为变量
  • 将x评估为值 - 它为1
  • 将x ++评估为值.这会将x计算为变量,然后将其原始值(即1)递增,然后递增该值(即2),然后将2分配给x,然后生成原始值,即1.
  • 评估1 + 1,即2
  • 将2分配给y.

所以x和y在C#中都是2.

C++可以做同样的事情,但允许以从右到左的顺序评估添加.也就是说,允许这样做:

  • 将x ++评估为值.这会将x计算为变量,然后将其原始值(即1)递增,然后递增该值(即2),然后将2分配给x,然后生成原始值,即1.
  • 将x评估为一个值 - 它是2
  • 评估1 + 2,即3
  • 将y评估为变量
  • 将3分配给y.

C++也允许这样做:

  • 将x ++评估为值.这将x作为变量进行求值,然后取其原始值1,然后递增该值,这是2 ...步骤缺失...然后得到原始值,即1.
  • 将x评估为值 - 它为1
  • 评估1 + 1,即2
  • 将2分配给x - 之前缺少的步骤.
  • 将y评估为变量
  • 将2分配给y.

所以在C++中,你可以得到y为3或2,这取决于编译器编写者的心血来潮.在C#中,你总能得到y是2.在C++中,增量的分配可以发生在任何时间,只要它确实发生了.在C#中,增量的赋值必须计算递增的值之后使用原始值之前发生.(从正在执行的线程中观察;如果你试图从另一个线程或线程中观察这些东西,所有的赌注都会关闭.)

在你的第二个例子中:

y = x++ + x; 
Run Code Online (Sandbox Code Playgroud)

在C#中,所需的行为是:

  • 将y评估为变量
  • 将x ++评估为值.这会将x计算为变量,然后将其原始值(即1)递增,然后递增该值(即2),然后将2分配给x,然后生成原始值,即1.
  • 将x评估为一个值 - 它是2
  • 评估1 + 2,即3
  • 将3分配给y.

所以C#中的正确答案是y是3而x是2.

同样,C++可以按任何顺序执行这些步骤.允许C++:

  • 将x评估为值 - 它为1
  • 将x ++评估为值.这会将x计算为变量,然后将其原始值(即1)递增,然后递增该值(即2),然后将2分配给x,然后生成原始值,即1.
  • 评估1 + 1,即2
  • 将y评估为变量
  • 将2分配给y.

同样,在C++中,正确答案是y为2或3,具体取决于编译器编写者的心血来潮.在C#中,正确的答案是y是3.

  • 总结:如果你有`x ++`或`++ x`,那么`x`最好不要在那条线上的任何其他地方. (16认同)

Mar*_*ers 28

  • 在C#中,操作数+以从左到右的顺序进行评估.
  • 在C和C++中,操作数的评估顺序+是未指定的.

对于C#,您的示例工作如下:

 y = x + x++;
     ^ x is 1
         ^ x is increased to 2, but the postfix increment returns the old value (1)
 y = 2

 y = x++ + x;
     ^ x becomes 2, but postfix increment returns the old value (1)
           ^ x is now 2 here
 y = 3
Run Code Online (Sandbox Code Playgroud)

  • 这并没有真正解决他的问题,但在两个例子中他都使用postfix.我没有方便的C或C#环境,所以我很好奇别人有什么话要说. (2认同)
  • 请注意Mark的措辞。正如Mark所指出的,(在C#中)x ++的意思是“递增x的值,然后返回x的旧值。x ++并不意味着:返回x的值,然后递增`x`。 (2认同)

Lou*_*Lou 6

在这两种情况下,在使用x之后应用增量.在第一个中,它被评估如下:y = 1 + 1(增加到2)

在第二

y = 1(递增到2)+ 2.

这就是你得到不同答案的原因.


Alo*_*ave 6

在C和C++中:
输出未指定.

参考 - C++ 03标准:

第5节:表达式,第4段:

除非注明[例如&&和||的特殊规则],否则各个运算符的操作数和各个表达式的子表达式的评估顺序以及副作用发生的顺序是未指定的.

在C99第6.5节中.

"运算符和操作数的分组由语法表示.72除了后面指定的(对于函数调用(),&&,||,?:和逗号运算符),子表达式的评估顺序和顺序发生副作用的都是未指明的."