Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

int[] arr={0}; int value = arr[arr[0]++]; Value = 1?

Today I came a cross an article by Eric Lippert where he was trying to clear the myth between the operators precedence and the order of evaluation. At the end there were two code snippets that got me confused, here is the first snippet:

      int[] arr = {0};
      int value = arr[arr[0]++];

Now when I think about the value of the variable value, I simply calculate it to be one. Here's how I thought it's working.

  1. First declare arr as an array of int with one item inside of it; this item's value is 0.
  2. Second get the value of arr[0] --0 in this case.
  3. Third get the value of arr[the value of step 2] (which is still 0) --gets arr[0] again --still 0.
  4. Fourth assign the value of step 3 (0) to the variable value. --value = 0 now
  5. Add to the value of step 2 1 --Now arr[0] = 1.

Apparently this is wrong. I tried to search the c# specs for some explicit statement about when the increment is actually happening, but didn't find any.
The second snippet is from a comment of Eric's blog post on the topic:

 int[] data = { 11, 22, 33 }; 
 int i = 1;
 data[i++] = data[i] + 5;

Now here's how I think this program will execute --after declaring the array and assigning 1 to i. [plz bear with me]

  1. Get data[i] --1
  2. Add to the value of step 1 the value 5 --6
  3. Assign to data[i] (which is still 1) the value of step 2 --data[i] = 6
  4. Increment i -- i = 2

According to my understanding, this array now should contain the values {11, 27, 33}. However, when I looped to print the array values I got: {11, 38, 33}. This means that the post increment happened before dereferencing the array!
How come? Isn't this post increment supposed to be post? i.e. happen after everything else.
What am I missing guys?

like image 753
Galilyou Avatar asked Aug 11 '09 13:08

Galilyou


2 Answers

The postincrement operation occurs as part of evaluating the overall expression. It's a side effect which occurs after the value is evaluated but before any other expressions are evaluated.

In other words, for any expression E, E++ (if legal) represents something like (pseudo-code):

T tmp = E;
E += 1;
return tmp;

That's all part of evaluating E++, before anything else is evaluated.

See section 7.5.9 of the C# 3.0 spec for more details.


Additionally, for assignment operations where the LHS is classified as a variable (as in this case), the LHS is evaluated before the RHS is evaluated.

So in your example:

int[] data = { 11, 22, 33 }; 
int i = 1;
data[i++] = data[i] + 5;

is equivalent to:

int[] data = { 11, 22, 33 }; 
int i = 1;
// Work out what the LHS is going to mean...
int index = i;
i++;
// We're going to assign to data[index], i.e. data[1]. Now i=2.

// Now evaluate the RHS
int rhs = data[i] + 5; // rhs = data[2] + 5 == 38

// Now assign:
data[index] = rhs;

The relevant bit of the specification for this is section 7.16.1 (C# 3.0 spec).

like image 124
Jon Skeet Avatar answered Nov 16 '22 00:11

Jon Skeet


For the first snippet, the sequence is:

  1. Declare arr as you described:
  2. Retrieve the value of arr[0], which is 0
  3. Increment the value of arr[0] to 1.
  4. Retrieve the value of arr[(result of #2)] which is arr[0], which (per #3) is 1.
  5. Store that result in value.
  6. value = 1

For the second snippet, the evaluation is still left-to-right.

  1. Where are we storing the result? In data[i++], which is data[1], but now i = 2
  2. What are we adding? data[i] + 5, which is now data[2] + 5, which is 38.

The missing piece is that "post" doesn't mean "after EVERYTHING else." It just means "immediately after I retrieve the current value of that variable." A post increment happening "in the middle of" a line of code is completely normal.

like image 28
VoteyDisciple Avatar answered Nov 16 '22 01:11

VoteyDisciple