I have been given a legacy code, where someone(s) have carelessly assigned double values to int variables like:
int a = 10;
double b = 20;
a = b;
Now to get rid of the
warning C4244: '=': conversion from 'double' to 'int', possible loss of data
warnings, I tried editing the code upstream and get rid of the unnecessary double variables, but it turns out to be too messy!
I could also use casting:
a = (int) b;
but actually there is no guarantee that b will be within the limits of an integer. I thought of making a helper function:
int safeD2I(double inputVar){
if ((inputVar < INT_MAX) && (INT_MIN < inputVar)){
return (int) inputVar;
} else {
exit(-1);
}
}
but I'm not sure if this is the best implementation. I was wondering if there is a more canonical way to handle this issue?
what I want:
- in the case the
bvariable being outside of the integer bounds, the program stops immediately - prints an error message to the terminal indicating that the specific line and time when this issue happened.
Thanks for your support in advance.
First, there's nothing inherently wrong or unsafe with the code as-is. Conversion by assignment is a completely legitimate part of the C language. If this is legacy code where you don't know if it's being done safely or not, you need to do the analysis to determine that.
If you find that you do need to catch possible out-of-bounds values (which produce undefined behavior (!!) when converted to
int), your code is both wrong and fragile. Comparisons like:coerce
INT_MAXto typedoublefor the comparison. In practice in a world wheredoubleis IEEE double andintis 32-bit, this happens to be safe, but it would be unsafe for example if you changeddoubletofloat, since a 32-bitINT_MAXis not representable in single-precisionfloat. The value will be rounded, and then the comparison takes place after the rounding.Now, it turns out you also have an off-by-one error (
<= INT_MAX, not< INT_MAX, is what's in-bounds) as well as incorrect logic (||instead of&&) so the rounding would actually fix part of that. But it's not right to depend on it. Instead you need to manufacture a power of two you can compare against, so it's safe to convert to floating point. For example:if (x < 2.0*(INT_MAX/2+1) && x >= INT_MIN)if (-x > (-INT_MAX-1) && x >= INT_MIN)if (-x > INT_MIN && x >= INT_MIN)These all assume
INT_MINis actually a power of two (full range twos complement) which is a reasonable real-world assumption and required by C2x+. If you want more generality it's more work.Finally, I first wrote this as a comment on your question, but the more I think about it, it really belongs in an answer: Based on what your C proficiency seems to be, I would be very wary of making any unnecessary or "cleanup" changes to this code. You are likely to break far more than you fix. Make changes only where you've done analysis to determine that there's an active bug, and don't refactor things or change types to fix. Make simple direct inline fixes.