在c/.net中,为什么它等于它的值?(我故意把答案漏掉,这样你就可以猜出来,看你是不是对了)
- 它的行为就是这样的,因为你永远不应该做那样的事情,因此这种行为是不相关的。
- 有趣的问题!
- 我不应该怀疑自己。似乎很明显,直到我想了一下。我认为20的理由是,直到引用之后才发生递减,然后我开始胡乱地想,当操作强制时,原始引用将递减,但它是一个值类型,但我猜是19。愚蠢的我。
- @Stefan-即使你总是写好代码,对一种语言有一个深入的理解也没有关系。你可能不会完全运用你的知识,但当有人需要帮助时,你会更加自信。
- @天空:它与"值类型"没有任何关系,与操作顺序也没有关系(分配发生在减量之后,减量发生在对rhs值进行解析之后,减量发生在加法之后)。
- 在jon skeets解释之后,我很好奇有多少编译器会优化——。
- @斯图尔特B:我只是重构一下以避免这个问题。如果您必须真正考虑编程语言的一个基本部分才能使其正常工作,那么您可能做得不对,或者有一种更好的语言适合您的工作。
- 像这样的问题应该叫做泥鸽…适合双向飞碟射击。
- @斯蒂芬-我想有些人只是不欣赏编程的纯学术方面。;)
- @吉米,这是我的第一个想法,只是被困住了。愚蠢的我。谢谢。
- 可能是x=x++;与x++;的区别是什么?
看看这句话:
这相当于:
相当于:
1 2 3
| int a1 = x; // a1 = 10, x = 10
int a2 = x--; // a2 = 10, x = 9
x = a1 + a2; // x = 20 |
因此,x之后是20——这是规范所保证的。
虽然规范中没有这样的规定,但也可以很好地保证,任何使用这种代码的人都会受到同事的攻击。是的,结果是可以预测的,这很好。不,使用这种代码不好。
- 不公平……双向飞碟不应该被允许回答这些问题。P
- 哈哈,禁止双向飞碟!!!!贪心!哈哈。
- @卡博特-不幸的是,似乎没有其他人能理解x和x之间的区别!
- 我想知道乔恩是不是根据记忆做的。
- 当然,为什么不呢,但我们都会释放出我们投入到寻找答案中的激动和能量,比乔恩·斯基特来得早。这是最有趣的部分。!!
- 如果他用X来代替呢?规范也保证了吗?
- @汤姆:是的,我有。当然,我事后检查过了。我得核实一下你把x指定为int,不过……如果x是byte的话,第一个"相当于…"的词会有细微的不同,即使在这种情况下结果是相同的。
- @贾斯汀:是的,这将保证产生19个-A2在扩建中的价值将是9。如果你把它改成x = --x + x;,你可以达到18。
- +1代表"…任何使用此类代码的人都将受到其同事的攻击…"
乔恩当然是对的。
思考这一点的一个好方法是记住:
1)子表达式始终从左到右进行计算。时期。评估子表达可能会引起副作用。
2)运算符的执行始终按照括号、优先级和关联性指示的顺序进行。执行操作可能会产生副作用。
+=左边的"x"是最左边的子表达式,因此规则(1)适用。它的值首先计算出来——10。
+=右边的x——是从左到右的下一个顺序,所以接下来对它进行计算。x的值是10,副作用是x变成9。这是应该的,因为--的优先级高于+=,所以它的副作用首先运行。
最后,+=的副作用持续到最后。两个操作数分别是10和10,所以结果是将20赋给X。
我一直都有关于这个的问题。记住,规则非常简单:从左到右的子表达式、按优先级排列的运算符、句点。
特别要注意的是,通常所说的推理"操作符是后缀,因此在所有其他操作之后运行"是错误的推理。我在下面的文章中讨论了为什么这是不正确的。
以下是我写的关于这个主题的一些文章:
http://blogs.msdn.com/ericlippert/archive/tags/precedence/default.aspx
- 加是C中的序列点?你允许人们在不理解序列点的情况下编写代码。世界末日就在眼前。
20;只有在对所有内容进行评估之后,"-"才会发生,并且该值将被等号的左侧覆盖。
- 你的名字不是乔恩·斯基特,但我还是会投赞成票。
- 虽然你得到了正确的答案,但你得到答案的逻辑是错误的。"在所有事情都得到评估之前不会发生"是误导性的。特别是,减量发生在9到x的赋值之前,10和10的加法之前,20到x的赋值之前。减量的计算发生在一个加法和两个赋值之前,所以不能正确地说,直到所有的东西都被评估,它才发生。
根据规范7.13.2
If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
所以你的陈述相当于从左到右的顺序进行评估并给出答案20的x = x + x--;。
注意,这里的--x和x--也有区别。如果你写了x += --x;,这相当于x = x + --x,那么你会得到19。这是因为x的值是递减的,结果的值用在表达式中(与x--不同,x的原始值用在表达式中)。
这个表达式x = x + --x + x将给出28,因为第三次的x被计算为9。
- 也许你的意思是20?10真是令人惊讶……)
- @弗朗切斯科:打字错误,已修复。现在我又加了一段,那10实际上就是10。
- +1用于引用规范。
- 虽然你在最后一段中提出的答案是正确的,但你的解释不太合理。在计算x之前不能进行递减,因为递减计算的值显然取决于x的计算结果!相反,正确的说法是表达式的值——x是减量后分配给x的值。也就是说,事件的顺序是:评估x(10),再次评估x(10),减去1(9),将9分配给x,将10和9(19),将19分配给x。有两个评估x,它们都发生在前面。
- @埃里克:是的,你说得对,"评估"这个词在那里用错了。谢谢你的纠正。我用自己的话重新措辞了。希望现在没事了。
- 更好,但仍然不完美。你的意思是第四次x的计算是"x=x+--x+x",它是9。第一个x在=的左侧进行计算,以确定存储的位置;这没有副作用,并且不使用它的值,但它是一个计算。然后在=的右侧评估为10。然后再次评估为10,计算10-1,9分配给X,9是操作的结果。然后,第四次计算x,现在是9。
- 例如,假设我们有t i(t t)console.writeline(t);return t;和class q public int x;并且您说i(q).x=i(q).x+--i(q).x+i(q).x;--您希望写入四行。储存位置的计算会产生副作用。注意,当你说i(q).x+=123时,副作用只发生一次;我们实际上并没有把它扩展到i(q).x=i(q).x+123;
- @埃里克:是的,关于评估数量的那一点实际上是在我答案开头的规范中提到的。感谢您耐心地纠正这些帖子中的错误。下次我会尽力把这个做好的。
答案是20。汤姆,你真的不像你的问题所暗示的那样惊讶,对吧?对于那些假设答案是19的人来说,我认为你和x+=--x混淆了;
- 他们所混淆的可能不是X,而是"减量X"的副作用是在计算+=运算符左侧之前还是之后发生的。在x+=x--从右向左计算的语言中,首先计算x--为10,然后将9赋给x,然后计算左边,现在是9。现在你把9加10,然后把它赋给x,所以,19。C确保表达式从左到右进行计算。C++没有,如果编译器选择的话,它可以从左到右评估,19和20都是合法结果。
- 埃里克。我相信你是对的。我不能再同意了。