I'm porting a legacy 16-bit C program from the Windows 3.0 era. I'm using C++ for many reasons. It makes some assumptions about math.
Let's say we have a function.
void myfunc(WORD addy);
Let's say I call this function like so:
myfunc((DWORD)some_integer - some_other_integer + (another_integer)*some_float);
In this case, the value should wrap-around below 0 to become 6690, but it gets passed as 0 - if it's important, this is passed into a .dll compiled in the same project.
However, moving that same exact expression with no variations into a variable like this:
WORD addy = (DWORD)some_integer - some_other_integer + (another_integer)*some_float;
EDIT: having (DWORD) in front still breaks it.
WORD addy = some_integer - some_other_integer + (another_integer)*some_float;
myfunc(addy);
results in the proper value being passed. The only difference is that the expression is evaluated outside of the function call and doesn't have a cast to DWORD in front of it.
This sort of behavior has led to more difficult-to-track-down bugs than I can try to describe.
Is there a compiler or linker switch to make it the default behavior not to pass 0 when evaluating an argument during a function call like this? And similar behavior other places, to enforce that -1 should be assumed to equal 0xFFFF (or 0xFFFFFFFF as the type may indicate)? Or is this a fundamental difference between C and C++?
Thank you.
EDIT:
This code was originally written in the Windows 3.0 days and has been compiled in Borland Turbo-Cxx products up to 4.5 and worked properly. The operator precedence nbelow
EDIT 2:
Here are the exact types in THIS case:
WORD addy = (DWORD cast)WORD_integer - WORD_integer_2 + (BYTE_value)*double_value;
CONCLUSION EDITED
According to IDEOne, C99 behavior differs from C++ behavior. C99: http://ideone.com/KI6i7H C++: http://ideone.com/gkQ5t2
Is there a compiler switch to change this to C99-style behavior?
You haven't provided the exact values of your variables, but it is obvious that you are relying on a floating-point-to-integer conversion.
This conversion does not perform wrap-around for unsigned targets either in C or C++. Instead, it produces undefined behavior in both C and C++ if the truncated floating-point value is out of range of the target integer type.
I suspect that this is exactly what happens in your case: the source floating-point value is out of range of
DWORD, which leads to undefined behavior.If you want your value to wrap-around when converted to unsigned type, you have to convert the floating-point value to a sufficiently large integer type first, and only after that you can convert it to
DWORD. If sufficiently large integer type does not exist, you have no other choice but the implement the desired behavior manually. Casts or implicit conversions will not help you with it.