4

i have small C code:

#include<stdio.h>
int main() 
{
    int  z[]= {1,2,3,4,5,6};
    int i = 2, j;
    printf("i=%d  \n",i); 

    z[i] = i++;

    for (j=0;j < 6;j++ )
       printf ("%d ", z[j]);

    printf("\ni=%d \n",i); 
}

output:

i=2  
1 2 2 4 5 6 
i=3

The order of precedence to evaluate the expression is First, z[i] is evaluated. As i is 2 here, it becomes z[2]. Next, i++ is evaluated i.e 2 is yielded and i becomes 3. Finally, = is executed, and 2 (i.e value yielded from i++) is put to z[2]

This explains the above output i.e 1 2 2 4 5 6

But if we change the above code from i++ to ++i i.e

#include<stdio.h>
int main() 
{
    int  z[]= {1,2,3,4,5,6};
    int i = 2, j;
    printf("i=%d  \n",i); 

    z[i] = ++i;

    for (j=0;j < 6;j++ )
       printf ("%d ", z[j]);

    printf("\ni=%d \n",i); 
}

Then the Output is strangely different, which is:

i=2  
1 2 3 3 5 6 
i=3

if we go by the above precedence (what C spec says [index] are bound earlier than ++) then the output should have been 1 2 3 4 5 6.

I just wish to know that why the above order of precedence does not explains this ?

my compiler is gcc 4.5.2 on ubuntu 11.04

Thanks and Regards, Kapil

Kapil
  • 836
  • 2
  • 8
  • 20

5 Answers5

5

z[i] = ++i; results in undefined behavior:

6.5 Expressions
...
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. 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) This paragraph renders undefined statement expressions such as

    i = ++i + 1;
    a[i++] = i;
while allowing

    i = i + 1;
    a[i] = i;

Note that precedence only controls the grouping of operators and operands; it does not control the order of evaluation.

The side effect of the ++ operator in ++i is unsequenced relative to the [] operator in z[i]; the compiler is not required to evaluate the two expressions in any particular order. Also note that the side effect of ++i need not be applied immediately after the expression is evaluated; it only needs to be applied before the next sequence point.

John Bode
  • 119,563
  • 19
  • 122
  • 198
3

This is not a bug, take a look at the GCC non-bug section. This kind of tests will cause unpredictable results and they know it.

Modifying a value twice between two sequence points [...] leads to undefined behavior.

aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
2
 z[i] = ++i;

is undefined behaviour

To quote from C section of cppreference.com

1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

i = ++i + i++; // undefined behavior

Suvarna Pattayil
  • 5,136
  • 5
  • 32
  • 59
0

z[i] = ++i;

invokes undefined behaviour.

Igmar Palsenberg
  • 637
  • 4
  • 10
0

See http://www.faqs.org/faqs/C-faq/faq/ Questions 3.1 to 3.9. These are pretty much answers to all questions similar to your question.

But in short, order of evaluation between two sequence points (these are well-defined by C standard - C99 Annex C) is undefined behavior.

Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored

obareey
  • 309
  • 2
  • 9