Подтвердить что ты не робот

Двойное к int неявное преобразование в mingw32

Я не могу объяснить поведение следующей программы (скомпилировано с gcc на mingw 32 бита). Я знаю о возможной потери точности при неявном преобразовании из double в int, но я бы ожидал, что два случая выдадут тот же результат, поскольку он выполняет те же самые операции. Почему два выхода отличаются друг от друга?

#include <stdio.h>
#include <math.h>

int main()
{
    int table[3] = {2, 3, 4};
    int i, N;

    N = 0;
    N += table[0] * pow(100, 0);
    N += table[1] * pow(100, 1);
    N += table[2] * pow(100, 2);
    printf("%d\n", N);

    N = 0;
    for(i = 0; i < 3; i++)
        N += table[i] * pow(100, i);
    printf("%d\n", N);

    return 0;
}

//output: 
40302
40300
4b9b3361

Ответ 1

С pow(100, 0) pow(100, 1) и pow(100, 2) компилятор заменяет вызовы функций константами (1, 100, 10000), но с pow(100, i) он должен фактически вызывать функцию во время выполнения (из-за переменной i передается как аргумент), что приводит к двум результатам pow в форме 0.99999999 и 99.999999 вместо 1 и 100 (или любых 2 из 3). При усечении до int после умножения вы теряете два блока.

Это еще один пример того, почему преобразование в int из double является просто чистым злом: очень сложно найти тонкие ошибки в вашей программе (а не ошибки компилятора).

Btw, я удивлен, что компилятор с O2 не разворачивал цикл, не распространял константы и не добивался той же оптимизации (заменяя вызов функции постоянными результатами).

Btw2 Поцарапайте это, я удивлен, что компилятор не просто заменил все ваши коды только двумя вызовами на printf.