В Visual Studio 2013 целочисленное математическое поведение со знаком / без знака отличается при оценке выражения как аргумента функции, переключателя компилятора?

Я портирую устаревшую 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?

1

Решение

Вы не предоставили точные значения ваших переменных, но очевидно, что вы полагаетесь на преобразование с плавающей точкой в ​​целое число.

Это преобразование не выполняет обтекание для неподписанных целей ни в C, ни в C ++. Вместо этого он производит неопределенное поведение как в C, так и в C ++, если усеченное значение с плавающей точкой выходит за пределы целевого типа.

Я подозреваю, что это именно то, что происходит в вашем случае: исходное значение с плавающей точкой выходит за пределы диапазона DWORD, что приводит к неопределенному поведению.

Если вы хотите, чтобы значение преобразовывалось в тип без знака, вы должны сначала преобразовать значение с плавающей запятой в достаточно большой целочисленный тип, и только после этого вы можете преобразовать его в DWORD, Если достаточно большой целочисленный тип не существует, у вас нет другого выбора, кроме как реализовать желаемое поведение вручную. Приведения или неявные преобразования не помогут вам в этом.

1

Другие решения


По вопросам рекламы [email protected]