InKwon Park
InKwon Park

Reputation: 41

Strange behavior from a simple C program

If I run the following code, graph[0][0] gets 1 while graph[0][1] gets 4.

In other words, the line graph[0][++graph[0][0]] = 4; puts 1 into graph[0][0] and 4 into graph[0][1].

I would really appreciate if anyone can offer reasonable explanation.

I observed this from Visual C++ 2015 as well as an Android C compiler (CppDriod).

static int graph[10][10];
void main(void)
{
    graph[0][++graph[0][0]] = 4;
}

Upvotes: 2

Views: 114

Answers (5)

AnT stands with Russia
AnT stands with Russia

Reputation: 320461

Let's line up the facts about this expression

graph[0][++graph[0][0]] = 4;
  • Per 6.5.1, the computation of the array index ++graph[0][0] is sequenced before the computation of array element graph[0][++graph[0][0]], which in turn is sequenced before the computation of the entire assignment operator.

  • The value of ++graph[0][0] is required to be 1. Note that this does not mean that the whole pre-increment together with its side-effects has to "happen first". It simply means that the result of that pre-increment (which is 1) has to be computed first. The actual modification of graph[0][0] (i.e. changing of graph[0][0] from 0 to 1) might happen much much later. Nobody knows when it will happen exactly (sometime before the end of the statement).

  • This means that the element being modified by the assignment operator is graph[0][1]. This is where that 4 should go to. Assignment of 4 to graph[0][1] is also a side-effect of = operator, which will happen sometime before the end of the statement.

Note, that in this case we could conclusively establish that ++ modifies graph[0][0], while = modifies graph[0][1]. We have two unsequenced side-effects (which is dangerous), but they act on two different objects (which makes them safe). This is exactly what saves us from undefined behavior in this case.

However, this is dependent on the initial value of graph array. If you try this

graph[0][0] = -1;
graph[0][++graph[0][0]] = 4;

the behavior will immediately become undefined, even though the expression itself looks the same. In this case the side-effect of ++ and the side-effect of = are applied to the same array element graph[0][0]. The side-effects are not sequenced with relation to each other, which means that the behavior is undefined.

Upvotes: 0

Sourav Ghosh
Sourav Ghosh

Reputation: 134326

First let's see what is the unary (prefix) increment operator does.

The value of the operand of the prefix ++ operator is incremented. The result is the new value of the operand after incrementation.

So, in case of

graph[0][++graph[0][0]] = 4;

first, the value of graph[0][0] is incremented by 1, and then the value is used in indexing.

Now, graph being a static global variable, due to implicit initialization, all the members in the array are initialized to 0 by default. So, ++graph[0][0] increments the value of graph[0][0] to 1 and returns the value of 1.

Then, the simpllified version of the instrucion looks like

graph[0][1] = 4;

Thus, you get

  • graph[0][0] as 1
  • graph[0][1] as 4.

Also, FWIW, the recommended signature of main() is int main(void).

Upvotes: 2

Bhavesh Kumar
Bhavesh Kumar

Reputation: 116

At first your variable graph[10][10] is static so it will be initialized with value 0.

Then line graph[0][++graph[0][0]] = 4 ; here graph[0][0] = 0 in expression you just incrementing the value of graph[0][0] so basically you assigning graph[0][1] = 4; yourself

Note that you have used pre-increment operator (++x) so it first get incremented and value is changed but if you would have use post-increment operator(x++) then graph[0][0] = 4; itself

Upvotes: 1

mart
mart

Reputation: 41

You are adding one to graph[0][0], by doing ++graph[0][0]. And then setting graph[0][1] to 4. Maybe you want to do graph[0][graph[0][0]+1] = 4

Upvotes: 1

Jashaszun
Jashaszun

Reputation: 9270

Let's break it down:

++graph[0][0]

This pre-increments the value at graph[0][0], which means that now graph[0][0] = 1, and then the value of the expression is 1 (because that is the final value of graph[0][0]).

Then,

graph[0][/*previous expression = 1*/] = 4;

So basically, graph[0][1] = 4;

That's it! Now graph[0][0] = 1 and graph[0][1] = 4.

Upvotes: 5

Related Questions