语言如何处理复合运算符的副作用?
假设这种情况:
int a = (--t)*(t-2);
int b = (t/=a)+t;
在 C 和 C++ 中,这是未定义的行为,如下所述: 未定义的行为和序列点
但是,这种情况在
- JavaScript、
- Java、
- PHP...
- C#
- 以及其他具有复合运算符的语言中是怎样的?
我正在修复 Javascript 的错误 ->现在的 C++ 移植在很多地方都没有注意到这一点。我想知道其他语言通常如何处理这个问题...保持未定义的顺序在某种程度上是 C 和 C++ 所特有的,不是吗?
Assume such situation:
int a = (--t)*(t-2);
int b = (t/=a)+t;
In C and C++ this is undefined behaviour, as described here: Undefined behavior and sequence points
However, how does this situation look in:
- JavaScript,
- Java,
- PHP...
- C#
- well, any other language which has compound operators?
I'm bugfixing a Javascript -> C++ port right now in which this got unnoticed in many places. I'd like to know how other languages generally handle this... Leaving the order undefined is somehow specific to C and C++, isn't it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据 ECMA 脚本规范,我相信 javascript 应该遵守该规范,在乘法和加法语句中,它会先评估左侧,然后再评估右侧。 (见 11.5 和 11.6)。我认为这意味着代码应该等效于
但是,您不应该总是相信规范与实现相同!
在这种令人困惑的情况下,最好的选择是在原始操作环境中对不明确的代码行进行各种输入试验,并尝试确定它在做什么。确保测试可以证实假设的案例,也测试可以证伪假设的案例。
编辑:显然大多数 JavaScript 都实现了 ECMAScript 第三版,所以我改为更改了该规范的链接。
According to the ECMA Script specification, which I believe javascript is supposed to conform to, in multiplication and addition statements, it evaluates the left hand side before evaluating the right hand side. (see 11.5 and 11.6). I think this means that the code should be equivalent to
However, you should not always trust the specification to be the same as the implementation!
Your best bet in confusing cases like this is to experiment with various inputs to the ambiguous lines of code in the original operating environment, and try to determine what it is doing. Make sure to test cases that can confirm a hypothesis, and also test cases that can falsify it.
Edit: Apparently most JavaScript implements the 3rd edition of ECMAScript, so I changed the link to that specification instead.
实际上,如果您必须询问或查找表达式的规则,则不应在代码中使用该表达式。其他人会在两年后回来发现错误,然后重写并破坏代码。
如果这是一个严格的理论问题,不幸的是我无法提供有关其他语言的详细信息。
Practically speaking, if you have to ask or look up the rules for an expression, you shouldn't be using that expression in your code. Someone else will come back two years from now and get it wrong, then rewrite it and break the code.
If this was intended as a strictly theoretical question I unfortunately can't offer details regarding those other languages.
对于 javascript,以下文章应该有所帮助。
本文清楚地说明了
a OP b OP c
的特定组合是否从左到右以及按什么顺序进行。我不知道其他语言。
For javascript the following article should help.
This article clearly states whether a particular combination of
a OP b OP c
goes from left-to-right and in which order.I'm don't know about the other languages.
坦白地说, int a = (--t)*(t-2); int b = (t/=a)+t; 看起来像废话。
拥有漂亮且精英主义的精美代码固然很好,但绝对没有必要。 每种语言在遇到这样的代码时的解决方案是添加几个分号(除非您正在处理 python):
如果需要不同的操作顺序,请调整行因此。如果您想修复旧的有缺陷的代码,请修复代码,而不要只是重新实现别人的意大利面条。
编辑添加:
我意识到我从未具体回答过原来的问题:
很糟糕。
To be perfectly candid,
int a = (--t)*(t-2); int b = (t/=a)+t;
looks like crap.It's nice to have fancy code that can be all pretty and elitist, but there's absolutely no need for it. The solution for every language when confronted with code like this is to add a couple more semi-colons (unless you're dealing with python):
If a different order of operations is desired, the adjust the lines accordingly. If you're trying to fix old buggy code, fix the code, don't just re-implement someone else's spaghetti.
Edit to add:
I realized I never specifically answered the original question:
Poorly.