I want the following idea: I have short a = -4;
and I have an unsigned short b = (unsigned short)a;
When I printf("%hu", b)
, why doesn't it print 4
? How can I convert a negative integer to a positive integer using casting?
CodePudding user response:
short
and unsigned short
are normally 16 bit integers. So limits are -32768 to 32767 for the signed version (short
) and 0 to 65535 for unsigned short
. Casting from signed to unsigned just wraps values, so -4 will be casted to 65532.
This is the way casting to unsigned works in C language.
If you accept to use additions/substractions, you can do:
65536l - (unsigned short) a
The operation will use the long
type (because of the l
suffix) which is required to be at least a 32 bits integer type. That should successfully convert any negative short integer to its absolute value.
CodePudding user response:
It sounds like you want the absolute value of the number, not a cast. In C we have the abs
/ labs
/ llabs
functions for that, found in <stdlib.h>
.
If you know ahead of time that the value is negative, you can also just negate it: -a
.
CodePudding user response:
If you were instead just looking to get the absolute value, you should have used the abs()
function from <stdlib.h>
.
Otherwise, when you make such a cast, you trigger the following conversion rule from C17 6.3.1.3:
Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type. 60)
Where foot note 60) is important:
- The rules describe arithmetic on the mathematical value, not the value of a given type of expression.
Mathematical value meaning we shouldn't consider wrap-around etc when doing the calculation. And the signedness format (2's complement etc) doesn't matter either. Applying this rule, then:
- You have mathematical value
-4
and convert fromsigned short
tounsigned short
. - We add one more than the maximum value. That is
-4 USHRT_MAX 1
, whereUINT_MAX
is likely 2^16 = 65535. -4 65535 1 = 65532
. This is in range of the new typeunsigned short
.- We got in range at the first try, but "repeatedly adding or subtracting" is essentially the same as taking the value modulo (max 1).
This conversion is well-defined and portable - you will get the same result on all systems where short
is 16 bits.
CodePudding user response:
That's not how casting works.
What you do with b
there is called integer overflow. Because b
is of type unsigned
, and you try to make it hold a negative number. This wưill result in integer overflow, and will return 65532
.
It seems like what you want is the abs()
function and its many types. See here.