There are many questions on the web on how to fix a specific signed/unsigned mismatch, and the solution is usually just making one variable unsigned. However, I've never found a decent discussion on dealing with it when you "need" one to be unsigned, and the other to be signed.
I've hit this issue multiple times but I'll just share my most recent.
I have a grid (x,y) which should be unsigned, since you can't have a (-5,-3) sized grid. However, I have a Direction object which should be signed, since I can have a (-1, -1) direction. The problem is when I do something like Location_x + Direction_x > grid_x which throws the signed/unsigned mismatch warning.
Now, there are multiple ways to deal with that one example, but that's not the question.
Rather, what kinds of similar situations have you been in, and how do you prefer to go about dealing with it?
And as a reminder, this is a discussion thread, I'm not looking for an answer to my example.
I try to always use signed types (specifically, int) wherever practical.
This provides the benefit of having uniformity and ease of use among types/functions. I don't have to worry about whether or not this particular function of this particular class is of type unsigned or signedlong or unsignedlonglong or std::size_t because everything is just an int.
Sometimes (like when dealing with file offsets) I will want a bigger type.. so I typically will use int64_t there. But in general... I just stick with ints.
In cases where signed types don't make logical sense (like for array/grid sizes) -- I use them anyway and validate their contents before applying them.
I prefer to avoid signed types because signed overflow is deadly UB, while unsigned overflow is just a wrap-around I can keep under control with asserts and tests.
As for location and direction, it's the same way in the library (size_type vs. difference_type) and even in the core language (size_t vs ptrdiff_t). Nothing to be surprised about.
I prefer to avoid signed types because signed overflow is deadly UB, while unsigned overflow is just a wrap-around I can keep under control with asserts and tests.
It's easy to check for a signed over flow assert(value >= 0), can't say the same for unsigned. If your code doesn't handle negative numbers, and you write it assuming that the numbers will never be negative using signed types then yah it's going to be a problem.
Which is what happens if it overflows, just about every CPU uses 2's complement as the integer representation. I don't think i've even seen a CPU that doesn't.
#include <iostream>
#include <cassert>
int main() {
int i = 1;
int c = 0;
do {
c ++;
i += i;
assert(i >= 0);
std::cout << i << std::endl;
} while (i >= 0);
std::cout << c << std::endl;
return 0;
}
assert should never be used for logic control. It is called DEBUG assertion for a reason. Its only use is to force program to file and get you a nice debugging point.
1) Assert just shuts you program. You cannot intercept failed assertion, gracefully handle it... It crashes. That's all
2) Asserts are thrown out completely when you compile your program in release mode.
3) assert is a macro.
Yes, as debugging aid. Not as only check. My statement Its only use is to force program to fail and get you a nice debugging point. does not contaradict you point.