Я сейчас работаю со старым кодом, который должен работать на 32-битной системе.Во время этой работы я наткнулся на проблему, из-за которой (из академического интереса) я хотел бы понять причину.
Кажется, что приведение от float к int в 32-битном C ведет себя иначе, если приведение выполненопо переменной или по выражению.Рассмотрим программу:
#include <stdio.h>
int main() {
int i,c1,c2;
float f1,f10;
for (i=0; i< 21; i++) {
f1 = 3+i*0.1;
f10 = f1*10.0;
c1 = (int)f10;
c2 = (int)(f1*10.0);
printf("%d, %d, %d, %11.9f, %11.9f\n",c1,c2,c1-c2,f10,f1*10.0);
}
}
Скомпилировано (с использованием gcc) либо непосредственно в 32-битной системе, либо в 64-битной системе с использованием модификатора -m32
. Вывод программы:
30, 30, 0, 30.000000000 30.000000000
31, 30, 1, 31.000000000 30.999999046
32, 32, 0, 32.000000000 32.000000477
33, 32, 1, 33.000000000 32.999999523
34, 34, 0, 34.000000000 34.000000954
35, 35, 0, 35.000000000 35.000000000
36, 35, 1, 36.000000000 35.999999046
37, 37, 0, 37.000000000 37.000000477
38, 37, 1, 38.000000000 37.999999523
39, 39, 0, 39.000000000 39.000000954
40, 40, 0, 40.000000000 40.000000000
41, 40, 1, 41.000000000 40.999999046
42, 41, 1, 42.000000000 41.999998093
43, 43, 0, 43.000000000 43.000001907
44, 44, 0, 44.000000000 44.000000954
45, 45, 0, 45.000000000 45.000000000
46, 45, 1, 46.000000000 45.999999046
47, 46, 1, 47.000000000 46.999998093
48, 48, 0, 48.000000000 48.000001907
49, 49, 0, 49.000000000 49.000000954
50, 50, 0, 50.000000000 50.000000000
Следовательно, очевидно, что существует различие между приведением переменной и выражения.Обратите внимание, что проблема существует также, если float
изменяется на double
и / или int
изменяется на short
или long
, также проблема не проявляется, если программа скомпилирована как 64-битная.
Чтобы прояснить, проблема, которую я пытаюсь понять, заключается не в арифметике / округлении с плавающей точкой, а скорее в различиях в обработке памяти в 32-разрядной системе.
Проблема была проверенаon:
универсальная версия Linux 4.15.0-45 (buildd @ lgw01-amd64-031) (версия gcc 7.3.0 (Ubuntu 7.3.0-16ubuntu3)), программа скомпилированаиспользование: gcc -m32 Cast32int.c
версия Linux 2.4.20-8 (bhcompile@porky.devel.redhat.com) (версия gcc 3.2.2 20030222 (Red Hat Linux 3.2).2-5)), программа скомпилирована с использованием: gcc Cast32int.c
Любые указатели, которые помогут мне понять, что здесь происходит, приветствуются.