Reputation: 1295
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
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
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
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
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,
int32_t
) can hold numbers between (-2^31) and (+2^31-1), INT_MIN
and INT_MAX
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
Reputation: 1
It becomes a negative number, unsigned data types dont hold negative number, so instead it becomes a large number
Upvotes: 0