Когда программа, как показано ниже, выполняется, она выдает нормальный результат:
j= 0 9007199616606190.000000 = x
k= 0 9007199616606190.000000 = [x]
r= 31443101 0.000000 = m*(x-[x])
Но когда закомментированная строка (т.е. //if (argc>1) r = atol(argv[1]);
) не закомментирована, она выдает:
j= 20000 9007199616606190.000000 = x
k= 17285 9007199616606190.000000 = [x]
r= 31443101 0.000000 = m*(x-[x])
хотя эта строка не должна иметь никакого эффекта, поскольку argc>1
ложно. Есть ли у кого-нибудь правдоподобное объяснение этой проблемы? Воспроизводима ли она на каких-либо других системах?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[]) {
int j, k, m=10000;
double r=31443101, jroot=sqrt(83), x;
//if (argc>1) r = atol(argv[1]);
x = r * r * jroot;
j = m*(x-floor(x));
k = floor(m*(x-floor(x)));
printf ("j= %9d %24.6f = x\n", j, x);
printf ("k= %9d %24.6f = [x]\n", k, floor(x));
printf ("r= %9.0f %24.6f = m*(x-[x]) \n", r, m*(x-floor(x)));
return 0;
}
Примечание, тестовая система = система AMD Athlon 64 5200+ с Linux 2.6.35.14-96.fc14.i686 (т.е. , загруженная для запуска 32-битной ОС на 64-битной HW) с gcc (GCC) 4.5. 1 2010924 (Red Hat 4.5.1-4)
Обновление -- Несколько часов назад я опубликовал комментарий о том, что код, сгенерированный с использованием оператора if
и без него, отличается только смещением стека и некоторым пропущенным кодом. Теперь я обнаружил, что этот комментарий был не совсем верен; т.е. он верен для неоптимизированного кода, но не верен для кода -O3, который я выполнил.
Влияние переключателя оптимизации на проблему:
j=20000
и k=17285
j=20000
(ошибка) и k=0
(OK)Так или иначе, глядя на листинги кода -O3 -S, эти два случая отличаются в основном пропущенным if
кодом и смещением стека до строки перед call floor
, в этот момент код with-if имеет на один fstpl
больше, чем код without-if:
... ;; code without comment:
fmul %st, %st(1)
fxch %st(1)
fstpl (%esp)
fxch %st(1)
fstpl 48(%esp)
fstpl 32(%esp)
call floor
movl $.LC2, (%esp)
fnstcw 86(%esp)
movzwl 86(%esp), %eax
...
... ;; versus code with comment:
fmul %st, %st(1)
fxch %st(1)
fstpl (%esp)
fxch %st(1)
fstpl 48(%esp)
fstpl 32(%esp)
fstpl 64(%esp)
call floor
movl $.LC3, (%esp)
fnstcw 102(%esp)
movzwl 102(%esp), %eax
...
Я не выяснил причину разницы.