What does i ++ really mean?

The question has been asked many times: "What is the difference between i ++ and ++ i". Accepted Answer What is the difference between i ++ and ++ i? , and I saw this language in many other places, so that 'i ++ means' tell me the value i, then increment', whereas ++ I means' increment i, and then tell me the value '.

What bothers me is that I didn’t know that we were discussing the return value for me in any scenario. I thought I ++ was syntactically equivalent:

i = i + 1; 

which is an expression, not an expression, so I don’t understand where I am returning at all.

Can you explain what a statement really means?

Thanks,

+7
c #
source share
3 answers

Edit: See Eric's answer , mine is meh.


You're right. ++ equivalent to i = i + 1 , but remember that i = i + 1 is not only an operator, but can also be used as an expression:

 Console.WriteLine((i = i + 1) * 42); // will inc i, and then print i*42 Console.WriteLine(++i * 42); // exactly same Console.WriteLine(i++ * 42); // will inc i, and print old_i*42 Console.WriteLine((i++) * 42); // exactly same 

So simple:

 // this int j = ++i * 42; // behaves like int j = (i = i + 1) * 42; // but this int j = i++ * 42; // actually behaves like int prev = i; i = i + 1; int j = prev * 42; 
+11
source share

For reasons unknown to me, this old question with an accepted answer today attracts new answers, many of which contain significant errors or omissions. Let me try to answer the question as asked definitively.

The question has been asked many times: "What is the difference between i ++ and ++ i". The accepted answer to [...], and I saw this language in many other places, is that "i ++ means" tell me the value of i and then increment ", whereas ++ I mean" increment i, then tell me the meaning.

As I already noted in my answer to the same question: this characteristic is widespread and reasonable in the first place in understanding, but, unfortunately, it is misleading when you look at semantics more closely. Please do not mislead this vague and not entirely accurate characterization. Instead, read my answer to this question.

What bothers me is that I didn’t know that we were discussing the return value for me in any scenario. I thought i++ syntactically equivalent to i = i + 1; , which is an expression, not an expression, so I don’t understand where I am returning at all.

You have a few misunderstandings here. Instead of attacking everyone, let's just say what the truth is.

First, ++i and i++ are not syntactically exactly equivalent to anything. You cannot take a legal program containing ++i or i++ and transform it exclusively syntactically into another legal program. So just get that thought out of your head. They are morally equivalent to increment and purpose and should be semantically equivalent, but not necessarily syntactic desuraring, which preserves programmatic semantics or legitimacy.

Let's say a few more true things. But first, some reservations. For the purposes of this discussion, the incremental expression i is an int variable that can be evaluated as a variable or value without side effects, including exceptions. Moreover, we assume that the increment of the operation does not raise an exception. And what's more, we assume one thread of execution. If you want to know the semantics of increments and assignments in cases where evaluating a variable may cause or produce another side effect or is not a variable, but rather is a property or operations are defined by the user or several flows are observed or changing the variable, see the specification for details .

However, here are some true facts:

  • ++i , i++ and i = i + 1 - expressions
  • ++i; , i++; and i = i + 1; are the operators
  • The semantics of ++i are as follows:

    • temp1 is set to i
    • temp2 is assigned the value temp1 + 1
    • I am assigned a temp2 value
    • expression value temp2
  • The semantics of i++ are as follows:

    • temp1 is set to i
    • temp2 is assigned the value temp1 + 1
    • I am assigned a temp2 value
    • expression value temp1
  • Please note that the difference between the two forms is only . The steps that are taken to get a side effect are the same in both cases . In single-threaded C #, you are guaranteed that the side effect will be completed before the value is produced.

  • The semantics of i = i + 1 is as follows:
    • temp1 is set to i
    • temp2 is assigned the value temp1 + 1
    • I am assigned a temp2 value
    • expression value temp2
  • Note that the semantics of i = i + 1 identical to the semantics of ++i . This is not a guarantee that you can syntactically replace i = i + 1 with ++i or vice versa, in an arbitrary program. In some programs this is possible.
  • Note that the semantics of i++ do not allow a “light” semantically equivalent form. ((Func<int, int, int>)((int j, int k)=>j))(i, i=i+1) has the same semantics, but obviously a crazy thing to input.

  • The semantics of the approval forms of all three:

    • Rate the expression as usual.
    • Discard the result.

I hope this will finally clarify any misunderstandings about what an expression is, what a statement is, what side effects and values ​​are generated by the expressions and in what order they occur. Again, note that this explanation is narrowly focused on simple cases involving whole variables without side effects for a single thread. Detailed information on how these operations work with other types or interact with exceptions or how they work in multi-threaded programs will consult the C # specification or ask a more specific question.

Finally: I personally still find all this confusing, and I have been programming descendants in C for 30 years, and I implemented this semantics in C #. If I find them confusing, and if almost every answer to every question that I see on these operators contains significant errors or omissions, then we can safely conclude that these are confusing operators. As a result, I almost never use ++ or -- in my production code. I think it is a bad style to have an expression that is useful both for its value and its side effects.

Try to find a way to structure your program so that the operator always has one side effect and the side expressions are limited to expressions. Avoid ++ and, in particular, avoid any scenario in which i++ and ++i will have different semantics, because the point at which the program will be more difficult to understand and therefore will be more difficult to maintain it correctly.

+16
source share

I think you can consider the following two functions to get an analogy with i++ and ++i .

Fiddle

 public static int IPlusPlus(ref int i) { // simply increment i before returning it i = i + 1; return i; } public static int PlusPlusI(ref int i) { // increment i only after you already returned it try { return i; } finally { i = i + 1; } } 

Just like function calls, i++ and ++i are right expressions , which means var a = i++; and var a = ++i; . But i++ = 5; and ++i = 5; invalid because they will use them as left expressions.

0
source share

All Articles