views:

89

answers:

3

This code has an interesting bug:

some_struct struct_array1[10] = {0};
some_struct struct_array2[10] = {0}
int i;

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     struct_array1[i].value = struct_array2[i++].value = 1)
    ;

For most compilers, the above code results in setting the "value" field of all structs in the respective arrays to 1. However, for one specific compiler (let's call it xcc), the structs in struct_array1 are NOT initialized correctly. The "value" field is set to 0 for all structs, which kind of surprised me.

The following code snippet works as expected on all compilers:

for (i = 0; 
     i < sizeof(struct_array1) / sizeof(struct_array1[0]); 
     i++)
{
    struct_array1[i].value = struct_array2[i].value = 1;
}

Now, am I completely off here, or does the offending compiler "xcc" simply display a bug?

I can't find anything that displays implementation-specific behavior in the first code snippet; from what I understand the postfix incrementation should have precedence over the assignments, and the assignments should be evaluated right-to-left. There should be nothing wierd with the first code snippet, except that it's a tad unreadable.

+5  A: 

struct_array1[i].value = struct_array2[i++].value = 1

I think that's undefined behaviour because i++ is not guaranteed to complete all of its side-effects until the next sequence point is reached. The next sequence point is the 'imaginary' ; at the end of the statement. That's a common pitfall, I think you can find many topics on SO pertaining to it, just search for sequence points.

Alexander Gessler
This is true. +1 from me.
the_drow
+7  A: 

You have invoked undefined behaviour, because it modifies i and also fetches its value for a purpose other than calculating the new value, without an intervening sequence point.

The relevant part of the C99 standard is this clause in section 6.5:

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

caf
Ah, of course. That does not explain why the second example works, but since it's undefined behavior I guess it does not have to be consistent :-)
Christoffer
The second example is OK because `i` is not modified - it is just read twice (the increment happens in a seperate expression, after a sequence point). The two objects that *are* modified are distinct (so that's OK too).
caf
Yeah, I'm actually a bit embarassed that I did not see it for my self, I suppose I needed another set of eyes to spot the problem. (To my defence I'd like to add that the proposed patch I was reviewing was ~500 lines of code, this was just one of the problems :-)
Christoffer
A: 

Actually we are not suppose to perform more than one evaluation for same variable, in signle

expression . If we do that thing, it will be undefined behaviour.

pavun_cool