简体   繁体   English

向其自身添加变量,其后缀增量在Java / c#中与在C中不同

[英]adding variable to itself with postfix increment different in Java/c# than in C

In Java and C# if I do this: 在Java和C#中,如果我这样做:

int i=1;
int j= i++ + i;

j is 3, ie it translates to 1+2 and increments i before the addition. j为3,即转换为1 + 2并在加法之前递增i。

However, in C j is 2, ie it translates to 1+1 then increments i. 但是,在C中j是2,即它转换为1 + 1,然后递增i。

What is the internal mechanism in C and Java/C# that causes this difference in what an expression is? 在C和Java / C#中导致这种表达式差异的内部机制是什么?

(the same goes for post-fix. Java/C# become 4 and C becomes 3.) (修复后也一样。Java/ C#变为4,C变为3。)

thanks. 谢谢。

Btw, initially I assumed it would be what the C answer was and so was confused by the Java/C# result. 顺便说一句,最初我以为这就是C答案,因此被Java / C#结果弄糊涂了。

Unlike Java and C# which specify precisely when the side effects would take place, C prohibits the use of an expression with side effects before the next sequence point . 与Java和C#明确指定发生副作用的时间不同,C禁止在下一个序列点之前使用具有副作用的表达式。 Not only does your expression produce a different result in C, but it is also undefined behavior. 您的表达式不仅会在C中产生不同的结果,而且还是未定义的行为。

In C, the mechanism is a finely-tuned celebration of compiler-writing skills affectionally known as Undefined behavior , or "UB". 在C语言中,该机制是对微调的编译器编写技巧的一种庆祝,通常被称为Undefined behavior或“ UB”。

In other words, nobody can provide an answer for C, since the code is known in advance to trigger undefined behavior. 换句话说,没有人可以提供C的答案,因为预先知道该代码会触发未定义的行为。 Anything could happen, there's no "right" or "wrong". 任何事情都可能发生,没有“正确”或“错误”。

From the 2011 draft of the C language standard : 2011年C语言标准草案开始

6.5 Expressions 6.5表达式

... ...
2 If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. 2如果相对于相同标量对象上的不同副作用或使用相同标量对象的值进行的值计算,相对于标量对象的副作用未排序,则行为未定义。 If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings. 如果一个表达式的子表达式有多个允许的排序,则如果在任何排序中都出现这种无序的副作用,则行为是不确定的。 84) 84)

3 The grouping of operators and operands is indicated by the syntax. 3语法指示运算符和操作数的分组。 85) Except as specified later, side effects and value computations of subexpressions are unsequenced. 85)除非后面有规定,否则子表达式的副作用和值计算是不顺序的。 86) 86)
84) This paragraph renders undefined statement expressions such as 84)本段呈现未定义的语句表达式,例如
\n    i = ++i + 1; i = ++ i +1;\n    a[i++] = i; a [i ++] = i;\n
while allowing 同时允许
\n    i = i + 1; 我=我+ 1;\n    a[i] = i; a [i] = i;\n

85) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same as the order of the major subclauses of this subclause, highest precedence first. 85)语法指定了运算符在表达式求值中的优先级,该优先级与此子节的主要子节的顺序相同,从最高优先级开始。 Thus, for example, the expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in 6.5.1 through 6.5.6. 因此,例如,允许作为二进制+运算符(6.5.6)的操作数的表达式是6.5.1至6.5.6中定义的那些表达式。 The exceptions are cast expressions (6.5.4) as operands of unary operators (6.5.3), and an operand contained between any of the following pairs of operators: grouping parentheses () (6.5.1), subscripting brackets [] (6.5.2.1), function-call parentheses () (6.5.2.2), and the conditional operator ? 例外情况是强制转换表达式(6.5.4)作为一元运算符(6.5.3)的操作数,以及以下任何一对运算符之间包含的操作数:分组括号()(6.5.1),下标括号[](6.5) .2.1),函数调用括号()(6.5.2.2)和条件运算符? : (6.5.15). :(6.5.15)。 Within each major subclause, the operators have the same precedence. 在每个主要子条款中,运算符具有相同的优先级。 Left- or right-associativity is indicated in each subclause by the syntax for the expressions discussed therein. 左或右关联在每个子句中由其中讨论的表达式的语法表示。

86) In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. 86)在程序执行过程中被多次评估的表达式中,不需要在不同的评估中一致地对其子表达式进行无序且不确定排序的评估。

The order in which the side effect of i++ is applied relative to the larger expression i++ + i is unspecified ; 相对于较大的表达式i++ + i而言, i++的副作用施加的顺序未指定 the two operations are unsequenced relative to each other. 这两个操作相对于彼此没有顺序。 If the side effect is applied immediately after i++ is evaluated, then you'll get the result of 1 + 2. If the side effect is deferred until after the addition, you'll get the result of 1 + 1. 如果在评估i++之后立即应用了副作用,那么您将得到1 + 2的结果。如果将副作用推迟到加法之后,您将得到1 + 1的结果。

The older version of the standard was a bit clearer; 该标准的较旧版本更加清晰。 an object may have its value modified at most once by the evaluation of an expression between sequence points, and the prior value of the expression is used only to determine the new value to be stored. 一个对象最多可以通过评估序列点之间的表达式来修改其值一次 ,并且该表达式的先验值仅用于确定要存储的新值。

The behavior is left undefined so that the compiler isn't required to detect these issues and issue a diagnostic ( i++ + i is easy enough to catch, but there are far more subtle variations of this problem that are a lot harder to detect). 行为未定义,因此不需要编译器来检测这些问题并发出诊断信息( i++ + i很容易捕获,但是此问题的细微变化要难得多)。 Either result is "correct" as far as the language definition is concerned. 就语言定义而言,任何一个结果都是“正确的”。

In C, post increment/decrement will be executed after the current operation is done. 在C语言中,当前操作完成后,将执行后递增/递减操作。 in this example, i++ + i; 在此示例中,i ++ + i; i will be incremented after the addition is done. 添加完成后,我将递增。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM