Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is it safe to subtract between unsigned integers?

Tags:

c

Following C code displays the result correctly, -1.

#include <stdio.h>

main()
{

    unsigned x = 1;
    unsigned y=x-2;

   printf("%d", y );

}
  1. But in general, is it always safe to do subtraction involving unsigned integers?
  2. The reason I ask the question is that I want to do some conditioning as follows:

    unsigned x = 1; // x was defined by someone else as unsigned, 
    // which I had better not to change.
    for (int i=-5; i<5; i++){
      if (x+i<0) continue
      f(x+i); // f is a function
    }
    

    Is it safe to do so?

  3. How are unsigned integers and signed integers different in representing integers? Thanks!

like image 744
Tim Avatar asked Dec 02 '22 16:12

Tim


1 Answers

1: Yes, it is safe to subtract unsigned integers. The definition of arithmetic on unsigned integers includes that if an out-of-range value would be generated, then that value should be adjusted modulo the maximum value for the type, plus one. (This definition is equivalent to truncating high bits).

Your posted code has a bug though: printf("%d", y); causes undefined behaviour because %d expects an int, but you supplied unsigned int. Use %u to correct this.

2: When you write x+i, the i is converted to unsigned. The result of the whole expression is a well-defined unsigned value. Since an unsigned can never be negative, your test will always fail.

You also need to be careful using relational operators because the same implicit conversion will occur. Before I give you a fix for the code in section 2, what do you want to pass to f when x is UINT_MAX or close to it? What is the prototype of f ?

3: Unsigned integers use a "pure binary" representation.

Signed integers have three options. Two can be considered obsolete; the most common one is two's complement. All options require that a positive signed integer value has the same representation as the equivalent unsigned integer value. In two's complement, a negative signed integer is represented the same as the unsigned integer generated by adding UINT_MAX+1, etc.

If you want to inspect the representation, then do unsigned char *p = (unsigned char *)&x; printf("%02X%02X%02X%02X", p[0], p[1], p[2], p[3]);, depending on how many bytes are needed on your system.

like image 146
M.M Avatar answered Dec 08 '22 17:12

M.M