How do languages handle side effects of compound operators?

时间:2021-10-23 15:13:15

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

在C和C ++中,这是未定义的行为,如下所述:未定义的行为和序列点

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?

我正在修复一个Javascript - > C ++端口,现在很多地方都没有注意到它。我想知道其他语言通常如何处理这个问题...保留命令undefined以某种方式特定于C和C ++,不是吗?

4 个解决方案

#1


7  

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

根据ECMA脚本规范,我认为javascript应该符合,在乘法和加法语句中,它在评估右侧之前评估左侧。 (见11.5和11.6)。我认为这意味着代码应该相当于

t = t - 1;
int a = t * (t - 2);
t = t / a;
int b = t + t;

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.

编辑:显然大多数JavaScript实现了ECMAScript的第3版,所以我改变了指向该规范的链接。

#2


3  

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.

如果这是一个严格的理论问题,我很遗憾无法提供有关其他语言的详细信息。

#3


2  

For javascript the following article should help.

对于javascript,以下文章应该有所帮助。

This article clearly states whether a particular combination of

本文明确说明是否特定组合

a OP b OP c goes from left-to-right and in which order.

OP OP OP从左到右依次排列。

I'm don't know about the other languages.

我不知道其他语言。

#4


1  

However, how does this situation look in: JS, Java, PHP, C#...

但是,这种情况如何:JS,Java,PHP,C#......

To be perfectly candid, int a = (--t)*(t-2); int b = (t/=a)+t; looks like crap.

坦率地说,int a =( - t)*(t-2); int b =(t / = a)+ t;看起来像废话。

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):

拥有漂亮而精致的花哨代码真是太好了,但绝对没有必要。面对这样的代码时,每种语言的解决方案是添加更多的分号(除非你正在处理python):

--t;
int a = t * (t-2);
t /= a;
int b = t + t;
-or-
int b = t * 2;
-or-
int b = t << 1;
//whichever method you prefer

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:

我意识到我从未专门回答原来的问题:

How do languages handle side effects of compound operators?

语言如何处理复合运算符的副作用?

Poorly.

#1


7  

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

根据ECMA脚本规范,我认为javascript应该符合,在乘法和加法语句中,它在评估右侧之前评估左侧。 (见11.5和11.6)。我认为这意味着代码应该相当于

t = t - 1;
int a = t * (t - 2);
t = t / a;
int b = t + t;

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.

编辑:显然大多数JavaScript实现了ECMAScript的第3版,所以我改变了指向该规范的链接。

#2


3  

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.

如果这是一个严格的理论问题,我很遗憾无法提供有关其他语言的详细信息。

#3


2  

For javascript the following article should help.

对于javascript,以下文章应该有所帮助。

This article clearly states whether a particular combination of

本文明确说明是否特定组合

a OP b OP c goes from left-to-right and in which order.

OP OP OP从左到右依次排列。

I'm don't know about the other languages.

我不知道其他语言。

#4


1  

However, how does this situation look in: JS, Java, PHP, C#...

但是,这种情况如何:JS,Java,PHP,C#......

To be perfectly candid, int a = (--t)*(t-2); int b = (t/=a)+t; looks like crap.

坦率地说,int a =( - t)*(t-2); int b =(t / = a)+ t;看起来像废话。

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):

拥有漂亮而精致的花哨代码真是太好了,但绝对没有必要。面对这样的代码时,每种语言的解决方案是添加更多的分号(除非你正在处理python):

--t;
int a = t * (t-2);
t /= a;
int b = t + t;
-or-
int b = t * 2;
-or-
int b = t << 1;
//whichever method you prefer

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:

我意识到我从未专门回答原来的问题:

How do languages handle side effects of compound operators?

语言如何处理复合运算符的副作用?

Poorly.