这个表达发生了什么?b = a +(a = a + 5)

fas*_*tec 66 c#

a = 5
b = a + (a = a + 5)
Run Code Online (Sandbox Code Playgroud)

结果b = 15

为什么第一个'a'在那之后没有变化(a = a + 5)?但为什么第二个改变?这步骤究竟发生了什么?

Jon*_*eet 161

表达式从左到右进行评估 - 始终,无论分组如何.所以它相当于:

a = 5;

int lhs = a; // 5
int rhs = (a = a + 5); // Increments a by 5 (i.e. a=10), and rhs=10
b = lhs + rhs; // 15
Run Code Online (Sandbox Code Playgroud)

所以在执行完之后,a 将会是10.但是这只发生在a主要加法的第一个操作数被评估之后,这就是为什么结果是15而不是20.

理解评估顺序与优先级不同的部分非常重要.考虑一下:

int x = First() + Second() * Third();
Run Code Online (Sandbox Code Playgroud)

优先级意味着乘法适用于调用的结果Second()Third()- 但First()仍然首先进行求值.换句话说,这个陈述相当于:

int lhs = First();
int rhs = Second() * Third();
int x = lhs + rhs;
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅Eric Lippert关于预定,关联性和排序的博客文章.

我强烈建议不要写这样的代码.

  • @WaqasShabbir:不,答案的重点是我的陈述与原始陈述*等同*.它不像原始语句在CPU中以原子方式执行.编译器将其分解为多个步骤(甚至我的答案可以分解为中间添加的额外步骤). (26认同)
  • @ArupRakshit:括号用于*分组*,而不是*order*.无论分组如何,表达式的LHS都是*始终*首先执行. (14认同)
  • @Erbureth:在C或C++中,订单未指定,但这个问题与这些语言无关. (10认同)
  • 所以_parens_没有得到**更高优先级你的意思吗?就像OP做的那样`(a = a + 5)` (3认同)

hac*_*cks 18

与C和C++不同,子表达式的评估顺序在C#中是从左到右.这就是表达的原因

j= ++i + ++i ;   
Run Code Online (Sandbox Code Playgroud)

在C#中有明确定义的行为,而在C和C++中未定义.

在表达中

b = a + (a = a + 5)  
Run Code Online (Sandbox Code Playgroud)

left a将首先进行评估,然后a+5进行评估,a并在添加两个评估的子表达式之后分配,b将具有值15.

  • @ user3294068:如果是"实现定义",那将是正确的.但它是_undefined_,这意味着程序可以做任何事情,包括崩溃. (4认同)
  • @BrianHannay; C标准说:***如果对标量对象的副作用相对于对同一标量对象的不同副作用**或使用相同标量对象的值计算值,则无效,**行为未定义***.这使得第一个语句处于未定义的行为之下.虽然第二个语句调用UB,因为C标准说:*如果表达式的子表达式有多个允许的排序,如果在任何排序中出现这样的无序副作用,则行为是不确定的*..... (2认同)

Waq*_*bir 10

表达式始终从左到右进行评估,然后分配给左手边的任何内容.如

  a = 5
  b = a + (a = a + 5)
\\b = 5 + (a = 5 + 5)
  b = 15
Run Code Online (Sandbox Code Playgroud)

  • *"但你的答案如何比乔恩的答案更好?"* - 这是一个微不足道的问题.它永远不会! (15认同)
  • 你说*但是,对于Jon的回答,我对你的回答并不满意.那很好,但你的答案如何比Jon的答案更好?还不清楚你想用第3行写的是什么?b = 5 +(a = 5 + 5)`至少用注释注释它,这样才有意义. (11认同)
  • 您的代码示例没有很好地解释.它意味着它在表达式的两个部分中同时替换a的值而不是它.在这种情况下它并不重要,但它可能会导致人们错误地应用相同的逻辑来得到`b =(a = a + 5)+ a`导致`b =(a = 5 + 5)+ 5` in一步是错的.你需要证明它首先完全评估LHS然后开始评估右边,例如包括`b = 5 +(a = a + 5)`作为你的中间步骤之一. (8认同)