reiallenramos
reiallenramos

Reputation: 1295

Using unsigned data types in C

How to use unsigned int properly? My function unsigned int sub(int num1, int num2);doesn't work when user input a is less than b. If I simply use int, we can expect a negative answer and I need to determine which is larger before subtracting. I know that's easy but maybe there is a way to use unsigned int to avoid that?

For instance when a = 7 and b = 4, the answer is 3.000000. But when I flip them, the code gives me 4294967296.000000 which I think is a memory address.

#include <stdio.h>

unsigned int sub(int num1,int num2){
    unsigned int diff = 0;
    diff = num1 - num2;
    return diff;
}

int main(){
    printf("sub(7,4) = %u\n", sub(7,4));
    printf("sub(4,7) = %u\n", sub(4,7));
}

output:

sub(7,4) = 3
sub(4,7) = 4294967293

Upvotes: 0

Views: 534

Answers (5)

Attie
Attie

Reputation: 6969

Unsigned numbers are unsigned... This means that they cannot be negative. Instead they wrap (underflow or overflow).

If you do an experiment with an 8-bit unsigned, then you can see the effect of subtracting 1 from 0:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint8_t i;

    i = 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    i -= 1;

    printf("i: %hhu\n", i);

    return 0;
}
i: 1
i: 0
i: 255

255 is the largest value that an 8-bit unsigned can hold (2^8 - 1).


We can then do the same experiment with a 32-bit unsigned, using your 4 - 7:

#include <stdio.h>
#include <stdint.h>

int main(void) {
    uint32_t i;

    i = 4;

    printf("i: %u\n", i);

    i -= 7;

    printf("i: %u\n", i);

    return 0;
}
i: 4
i: 4294967293

4294967293 is effectively 0 - 3, which wraps to 2^32 - 3.


You also need to be careful of assigning an integer value (the return type of your sub() function) to a float... Generally this is something to avoid.

See below. x() returns 4294967293 as an unsigned int, but it is stored in a float... This float is then printed as 4294967296???

#include <stdio.h>
#include <stdint.h>

unsigned int x(void) {
    return 4294967293U;
}

int main(void) {
    float y;

    y = x();

    printf("y: %f\n", y);

    return 0;
}
y: 4294967296.000000

This is actually to do with the precision of float... it is impossible to store the absolute value 4294967293 in a float.

Upvotes: 6

chux
chux

Reputation: 153338

"absolute value of the difference between a and b" does not work for many combinations of a,b. Any a-b that overflows is undefined behavior. Obviously abs(INT_MAX - INT_MIN) will not generate the correct answer.

Also, using abs() invokes undefined behavior with a select value of int. abs(INT_MIN) is undefined behavior when -INT_MIN is not representable as an int.

To calculate the absolute value difference of 2 int, subtract them as unsigned.

unsigned int abssub(int num1,int num2){
  return (num1 > num2) ? (unsigned) num1 - num2 : (unsigned) num2 - num1;
}

Upvotes: 0

wto
wto

Reputation: 221

unsigned int cannot be used to represent a negative variable. I believe what you wanted is to find the absolute value of the difference between a and b. If so, you can use the abs() function from stdlib.h. The abs() function takes in an int variable i and returns the absolute value of i.

The reason why unsigned int returns a huge number in your case is due to the way integers are represented in the system. You declared diff as an int type, which is capable of storing a negative value, but the same sequence of bits that represents -3 when interpreted as unsigned int represents 4294967296 instead.

Upvotes: 2

Venemo
Venemo

Reputation: 19067

What you see is called unsigned integer overflow. As you noted, unsigned integers can't hold negative numbers. So when you try to do something that would result in a negative number, seemingly weird things can occour.

If you work with 32-bit integers,

  • int (int32_t) can hold numbers between (-2^31) and (+2^31-1), INT_MIN and INT_MAX
  • unsigned int (uint32_t) can hold numbers between (0) and (2^32-1), UINT_MIN and UINT_MAX

When you try to add something to an int that would lead to a number greater than the type can hold, it will overflow.

Upvotes: 2

Luke
Luke

Reputation: 1

It becomes a negative number, unsigned data types dont hold negative number, so instead it becomes a large number

Upvotes: 0

Related Questions