Oh gcc…

Yes, I know about sequence points.. and I know we’re asking for trouble, and wantonly ignoring warnings of undefined behavior when using expressions with multiple side-effects to the same variable, but really.. a little consistency would be nice.

Take this code for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
 
void *i;
volatile void *j;
 
int main()
{
    void *k;
    volatile void *l;
    i = k = (void*)10;
    j = l = (void*)10;
    printf("%d\n", (++i) == (++i));
    printf("%d\n", (++j) == (++j));
    printf("%d\n", (++k) == (++k));
    printf("%d\n", (++l) == (++l));
    printf("%p %p %p %p\n", i, j, k, l); 
    i = k = (void*)10;
    j = l = (void*)10;
    printf("%d\n", (i++) == (i++));
    printf("%d\n", (j++) == (j++));
    printf("%d\n", (k++) == (k++));
    printf("%d\n", (l++) == (l++));
    printf("%p %p %p %p\n", i, j, k, l);
    i = k = (void*)10;
    j = l = (void*)10;
    printf("%d\n", (i++) && (i++));
    printf("%d\n", (j++) && (j++));
    printf("%d\n", (k++) && (k++));
    printf("%d\n", (l++) && (l++));
    printf("%p %p %p %p\n", i, j, k, l);
    return 0;
}

Can you predict what it’ll print? Here are my results with gcc-4.3.3.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
amandla> gcc test.c -o noopt
amandla> gcc -O test.c -o opt
amandla> ./noopt 
0
0
1
1
0xc 0xc 0xc 0xc
1
1
1
1
0xb 0xb 0xc 0xc
1
1
1
1
0xc 0xc 0xc 0xc
amandla> ./opt 
1
1
1
1
0xc 0xc 0xc 0xc
1
1
1
1
0xb 0xb 0xc 0xc
1
1
1
1
0xc 0xc 0xc 0xc
amandla>

Note how the first 2 values (results of comparisons) change when optimizations are applied and how the second set of printed pointers stubbornly contains some 0xb entries. Granted, if I add “-Wsequence-point” to my compile flags then gcc will suggest that my variables may be undefined state at a few places.

Interestingly, Intel’s compiler gives me something more in line with what I’d expect.. and bitches about my rampant abuse of the language without my needed to turn on any warning flags. With or without optimizations, the results are:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
amandla> ./icctest 
0
0
0
0
0xc 0xc 0xc 0xc
1
1
1
1
0xc 0xc 0xc 0xc
1
1
1
1
0xc 0xc 0xc 0xc
amandla>

I suppose I should be happy that gcc did not openly mocked the code in iambic pentameter or simply refused to compile it out of principle.

Leave a Comment