Consider for example:
extern void g(int);
void f(int x, int y)
{
g(x - y);
}
The function f obviously doesn't work for all values of x and y: Some values will overflow, some values will underflow.How do you fix that? Writing an explicit check for whether x-y overflows is highly impractical, no one does that.
Or you could document the limitation using pre- and postconditions that narrow down the range of allowed values to something you know will work:
extern void g(int);
void f(int x, int y)
/*
PRECONDITION: -1000000 <= x <= 1000000 and -1000000 <= y <= 1000000
*/
{
g(x - y);
}
No one does that either. I don't know why. There's no principled reason why you couldn't meticulously keep track of signed int input and output ranges. But that's how it is, no one does it, valid int ranges are always unstated.Now for the unsigned version of the same problem:
extern void g1(unsigned);
extern void g2(unsigned);
void f(unsigned x, unsigned y)
{
if(x >= y)
g1(x - y);
else
g2(y - x);
}
Assuming g1 and g2 are well-defined for all unsigned inputs, so is f. That was easy.It may look like more code, because there are two g functions now. But chances are you probably need to treat the x<y case differently somewhere anyway; in the larger scheme of things, unsigned is not more code.