Проблема с умножением на дробь при замещении перед процессором (#define)
Я хотел бы начать с кода
#define myConst (419*0.9)
#define myConst1 (419*.9)
#define myConst9 (myConst1*.9)
#define myConst11 (419*1.1)
int main()
{
printf("myConst:%d\n",myConst);
printf("myConst1:%d\n",myConst1);
printf("myConst9:%d\n",myConst9);
printf("myConst11:%d\n",myConst11);
return 0;
}
Что дало мне вывод как
MyConst: 1913895624
myConst1: 1
myConst9: 1
myConst11: 1
Я не знаю, почему умножение на дробь в #define приводит к значению, отличному от ожидаемого? А также значение myConst непрерывно меняется, например, некоторые значения, которые я наблюдал, составляют -254802840 -1713343480 466029496. А также myConst1,myConst9 и myConst11 дают мне 1, что, по моему мнению, не логично.
Любое объяснение относительно того же самого приветствуется.
1 ответ
#define
не играет никакой роли в этом; проблема в том, что вы передаете double
когда printf
ожидает int
(из-за %d
Спецификатор); технически это неопределенное поведение, так что все может произойти.
Теперь, если бы он был построен на 32-битной x86, вероятно, вы бы получили int
реинтерпретация младших 32 битов с плавающей запятой, поскольку все параметры обычно передаются в стеке. Но я думаю, что это работает на 64-битной x86, где параметры передаются в разные регистры, если они с плавающей запятой. В этом случае, printf
просто читает какой-то мусор, который находится в каком-то регистре в это время, в этих значениях не так много логики.
Обратите внимание, что почти любой компилятор может предупредить вас о таком несоответствии между строкой формата и фактически переданными значениями. Для gcc и clang я предлагаю вам включить это предупреждение (-Wformat
, включен в -Wall
, что вы должны обязательно включить), и, возможно, пометить его как фактическую ошибку (-Werror=format
), так как нет законных оснований нарушать printf
как это.