Бессмысленная оптимизация в C - PullRequest
0 голосов
/ 18 октября 2019

При использовании оптимизаций O2 и выше с gcc я получаю неожиданный вывод со следующим кодом.

#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 ) );
} 

Этот код обычно должен выводить «0 0», но вместо этого с -O2 выводится «1 0». Затем, если я удаляю printf из функции f, он просто печатает 1. Это тот же оператор printf, чей вывод был изменен линией печати.

Почему это происходит?

Также я знаю, что никогда не должен делать это, я просто хочу знать, почему это происходит.

1 Ответ

5 голосов
/ 18 октября 2019

С обоими -O0 и -O2 GCC 9.2 генерирует код, который выполняет *a = 1; первый и *b = 0; второй.

В неоптимизированномВ этом случае он загружает *a из памяти, чтобы передать его printf и вернуть. Так как i был установлен на 0 с помощью *b = 0;, загрузка его как *a дает 0, и это то, что печатается, а что возвращается.

В оптимизированном случае компилятор принимает *aи *b являются различными объектами, и, следовательно, *a = 1; установил значение *a равным 1, а *b = 0; не изменил его. Следовательно, при передаче *a в printf он пропускает 1, не загружая его из памяти. (1 жестко закодирован как непосредственный операнд в инструкции.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...