Я портирую устаревшую 16-битную C-программу из эпохи Windows 3.0. Я использую C ++ по многим причинам.
Это делает некоторые предположения о математике.
Допустим, у нас есть функция.
void myfunc(WORD addy);
Допустим, я называю эту функцию так:
myfunc((DWORD)some_integer - some_other_integer + (another_integer)*some_float);
В этом случае значение должно обернуться ниже 0, чтобы стать 6690, но оно передается как 0 — если это важно, оно передается в DLL, скомпилированную в том же проекте.
Однако, перемещая то же самое точное выражение без изменений в переменную, подобную этой:
WORD addy = (DWORD)some_integer - some_other_integer + (another_integer)*some_float;
РЕДАКТИРОВАТЬ: имея (DWORD) впереди все еще ломает его.
WORD addy = some_integer - some_other_integer + (another_integer)*some_float;
myfunc(addy);
приводит к правильной передаче значения. Единственное отличие состоит в том, что выражение вычисляется вне вызова функции и не имеет приведения к DWORD перед ним.
Такое поведение привело к более трудным для выявления ошибок, чем я могу попытаться описать.
Есть ли переключатель компилятора или компоновщика, чтобы сделать поведение по умолчанию не передавать 0 при оценке аргумента во время вызова функции, подобного этому? И подобное поведение в других местах, для обеспечения того, чтобы -1 предполагалось равным 0xFFFF (или 0xFFFFFFFF, как может указывать тип)? Или это принципиальная разница между C и C ++?
Спасибо.
РЕДАКТИРОВАТЬ:
Этот код был изначально написан в дни Windows 3.0 и был скомпилирован в продуктах Borland Turbo-Cxx до 4.5 и работал должным образом. Приоритет оператора n ниже
РЕДАКТИРОВАТЬ 2:
Вот точные типы в этом случае:
WORD addy = (DWORD cast)WORD_integer - WORD_integer_2 + (BYTE_value)*double_value;
ЗАКЛЮЧЕНИЕ
Согласно IDEOne, поведение C99 отличается от поведения C ++.
C99: http://ideone.com/KI6i7H
C ++: http://ideone.com/gkQ5t2
Есть ли переключатель компилятора, чтобы изменить это на поведение в стиле C99?
Вы не предоставили точные значения ваших переменных, но очевидно, что вы полагаетесь на преобразование с плавающей точкой в целое число.
Это преобразование не выполняет обтекание для неподписанных целей ни в C, ни в C ++. Вместо этого он производит неопределенное поведение как в C, так и в C ++, если усеченное значение с плавающей точкой выходит за пределы целевого типа.
Я подозреваю, что это именно то, что происходит в вашем случае: исходное значение с плавающей точкой выходит за пределы диапазона DWORD
, что приводит к неопределенному поведению.
Если вы хотите, чтобы значение преобразовывалось в тип без знака, вы должны сначала преобразовать значение с плавающей запятой в достаточно большой целочисленный тип, и только после этого вы можете преобразовать его в DWORD
, Если достаточно большой целочисленный тип не существует, у вас нет другого выбора, кроме как реализовать желаемое поведение вручную. Приведения или неявные преобразования не помогут вам в этом.