0

Basically this is a simple function that writes value to int array.
I want to assign a value to current element, print it and the index out, and self-increasing the index to next element.
However, the changes on order of self-increment makes the results different.

#include <stdio.h>

int buff[5];
int id;

void write ( )
{
    int i;
    i = id = 0;
    printf("Iter 1\n");
    while (i++ < 5) {
        buff[id] = id;
        printf("writes %d in buff[%d]\n", buff[id], id++);
    }

    i = id = 0;
    printf("Iter 2\n");        
    while (i++ < 5) {
        buff[id] = id;
        printf("writes %d in buff[%d]\n", buff[id++], id);
    }
}

int main ( )
{
    write();
}

-------------
Output:

Iter 1
writes 0 in buff[0]
writes 0 in buff[1]    // which should not be 0
writes 0 in buff[2]    // which should not be 0
writes 0 in buff[3]    // which should not be 0
writes 5 in buff[4]    // which should not be 5
Iter 2
writes 0 in buff[0]
writes 1 in buff[1]
writes 2 in buff[2]
writes 3 in buff[3]
writes 4 in buff[4]

I know that trying multiple self-increment operation on same variable in an expression may cause problem, but don't know why the self-increment style in Iter 1 here fails to return the correct value of id.

Thanks for any explanation or suggestion.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Lee
  • 535
  • 5
  • 19

3 Answers3

3

Your code has undefined behavior:

printf("writes %d in buff[%d]\n", buff[id], id++);

There is no sequence point between the moment you retrieve the value of id and modify it, the compiler is free to do whatever it wants.

The proper way of writing this would be:

printf("writes %d in buff[%d]\n", buff[id], id);
id++;

If you compile with warnings, you should getting something similar to:

test.c:21:50: warning: operation on ‘id’ may be undefined [-Wsequence-point]
         printf("writes %d in buff[%d]\n", buff[id++], id);
                                                  ^

Additional reading:

Community
  • 1
  • 1
netcoder
  • 66,435
  • 19
  • 125
  • 142
  • Thanks for the explanation and citation. My environment is gcc + Debian 3.2.41. – Lee Mar 24 '14 at 06:36
2

Both printf calls exhibit undefined behavior. You have two evaluations, unsequenced with respect to each other, one of which reads a scalar object id and the other modifies the same object.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
0

Note that you have the two variables in the wrong order in the first loop. I'm guessing the postincrement's happening before the printf reads buf, so you're reading into array elements that you haven't entered yet. Like, the order of operations is (speculatively) something like this:

write 0 to buf[0]
increment id to 1
read from buf[1]

write 1 to buf[1]
increment id to 2
read from buf[2]

Then the 5's from your array pointer going past the end of the array and reading id instead.

As Igor pointed out, this is undefined behavior, so it may act differently depending on the compiler/platform you're using, and should never be used in published code.

cactus1
  • 629
  • 5
  • 8