Earleking
Earleking

Reputation: 79

Non-nonsensical optimization in C

When using optimizations O2 and above with gcc I get unexpected output with the following code.

#include <stdio.h>

int f ( int *a, float *b ) {
    *a = 1;
    *b = 0;
    printf ( "%d ", *a );
    return *a;
}

int main ( ) {
    int i = 0;

    printf ( "%d\n", f ( &i, &i ) );
} 

This code normally should print "0 0" but instead with -O2 is prints "1 0". Then if I remove the printf in the function f it just prints 1. That is the same printf statement having its output changed by a printline.

Why does this happen?

Also I am aware I should never be doing this, I just want to know why it's happening.

Upvotes: 0

Views: 63

Answers (1)

Eric Postpischil
Eric Postpischil

Reputation: 224312

With both -O0 and -O2, GCC 9.2 generates code that performs *a = 1; first and *b = 0; second.

In the unoptimized case, it then loads *a from memory to pass it to printf and to return it. Since i was set to 0 by *b = 0;, loading it as *a produces 0, and that is what is printed and what is returned.

In the optimized case, the compiler assumes *a and *b are different objects and, therefore, that the *a = 1; has set the value of *a to 1, and that the *b = 0; did not change it. Consequently, when passing *a to printf, it passes 1 without loading it from memory. (The 1 is hard-coded as an immediate operand in an instruction.)

Upvotes: 5

Related Questions