Home > Software engineering >  how to avoid unsigned integer compare with signed number?
how to avoid unsigned integer compare with signed number?

Time:11-29

void main() {
    unsigned int a = 0;
    if (a - 10 < 0) {
        printf("error!\n");
    }
}

we know this comparison won't work, because a-10 will be a big unsigned integer, it can't be smaller than 0.

To avoid this situation, I try this:

void main() {
    unsigned int a = 0;
    int b = 0;// or const int b = 0;
    if (a - 10 < b) {
        printf("error!\n");
    }
}

this will get warning C4018 using Visual Studio 2022 17.2.4.

However, when I use gcc 4.8.5, there is no warning at all.

Is there a way to avoid coder compare signed number with unsigned variable?

Update: a more complex situation could be this:

struct s{
unsigned int len;
char *buffer;
} *a;

int not_safe(struct s *ptr){
 if(ptr->len - sizeof(struct s) < 0){
  return 0;
 }
 return 1;
}

Programmers may not be aware of such comparisons are wrong. I hope we can have a safe way to let programmer avoid this.

CodePudding user response:

If you cast the unsigned int operand to int:

if ((int)a - 10 < 0)

Then all of the math with be done using type int.

Or, you can do a little bit of algebra:

if (a < 10)

To avoid the problem completely.

CodePudding user response:

Please study what C formally calls the usual arithmetic conversions Implicit type promotion rules. The TL;DR is that in case you have two integers of the same size but different signedness, the signed one will get converted to unsigned.

You could explicitly cast the unsigned operand to signed. Or you could let the signed operand be a larger type than the unsigned, such as int64_t, in which case the unsigned int (likely 16 or 32 bits) will get converted to int64_t.

But that won't solve your root problem which is this line:

if(ptr->len - sizeof(struct s) < 0)

This is doesn't make any sense to begin with. And casting ptr->len to int64_t might not help either size sizeof returns a size_t, which is guaranteed to be a large unsigned integer type. Simply replace this with:

if(sizeof(struct s) > ptr->len)

Or if you will, change the whole function to one following common best practices:

bool not_safe (const struct s* ptr) {
  return sizeof(struct s) > ptr->len;
}
  • Related