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?
-
2You don't. That's not how casting works. – dbush Nov 29 '21 at 13:02
-
Can you explain me a little bit more so I can understand it? Thanks – Tenko Nov 29 '21 at 13:03
-
Because the meaning of a cast is *not* to compute the absolute value. The meaning of a cast is to convert one type to another, generally keeping the same value. In two's complement arithmetic, the number -4 is represented by a bit pattern which, if treated as a plain binary number, has the value 65532. So that's probably what the cast will give you. – Steve Summit Nov 29 '21 at 13:04
-
Is there any reason why you want to use a cast? – klutt Nov 29 '21 at 13:05
-
So it is impossible to do it by casting? the reason I want to use a cast is to undesratnd better how cast works – Tenko Nov 29 '21 at 13:07
-
@Tenko yep i'm afraid you can't do that. – justANewb stands with Ukraine Nov 29 '21 at 13:08
-
@Tenko It's true that casting a floating-point number to an integer throws away the fractional part, and therefore changes the value. You probably thought that casting a negative number to unsigned would throw away the `-` sign. But it just doesn't work that way. – Steve Summit Nov 29 '21 at 13:08
-
@Tenko If you want to fully understand casting, it's a surprisingly broad topic. It's also generally recommended *not* to use explicit casts very often. In modern C, the number of places where you might need an explicit cast is quite small. These days, most of the time, an explicit cast indicates someone doesn't quite know what they're doing, and may be hiding an error. – Steve Summit Nov 29 '21 at 13:16
-
@SteveSummit yeah, that is what i thought. I continue to missunderstand it. If I cast 167.98 to int , the new value will be 168, so why many people told me that the value is the same, the value has changed. It means that the binary number is the same but the form it is shown changes? – Tenko Nov 29 '21 at 13:35
-
@Tenko If you cast 167.98 to int, the new value will be 167, not 168. – Ian Abbott Nov 29 '21 at 13:58
-
@Tenko If you wanted to ask the broad question, "What are all the different cases for what a cast can do?", I wouldn't stop you, and you might get some good answers. There's quite a bit of good information at [this question](https://stackoverflow.com/questions/1942159/need-some-clarification-regarding-casting-in-c). I see a few other candidates while doing a Google search for "[what are the rules on casting C site:stackoverflow.com](https://www.google.com/search?q=what+are+the+rules+on+casting+C+site%3Astackoverflow.com)". – Steve Summit Nov 29 '21 at 14:07
3 Answers
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.

- 143,923
- 11
- 122
- 252
-
if I cast -4 I obtain 65632 and later if I operate 65632 - 65628 I obtain 4, so can I automate it so if the user introduces -5 it shows 5 casting it? – Tenko Nov 29 '21 at 13:12
-
1It is perhaps worth noting that this rule is asymmetric. Converting from signed to unsigned always wraps to the range of the unsigned, but it is implementation-defined whether converting from unsigned to signed does the same when the starting value is outside the range of the signed type. – John Bollinger Nov 29 '21 at 13:13
-
@Tenko, the combination of operations you describe is equivalent to -4 - 2 * (-4), so yes, you can cover additional negative integers that way. For example, `b = (unsigned short) a - 2 * (unsigned short) a`. But that is not the same as absolute value because it does not leave positive inputs unchanged. And it is not *just* casting. – John Bollinger Nov 29 '21 at 13:18
-
Actually you can change it to casting in both directions: cast "-1" to unsinged which will give you 65535 (for unsigned), subtract "a" and add 1 :) – Karol T. Nov 29 '21 at 14:00
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
.

- 112,504
- 36
- 218
- 315
-
Yeah, but I dont want to use the absolute value method, I want to do it by casting it – Tenko Nov 29 '21 at 13:04
-
1@Tenko Ok, but just because you want to use a hammer to paint your wall doesn't mean you can do it. – orlp Nov 29 '21 at 13:05
-
1@orlp Just like painting a wall with a hammer, you can do it but you won't like what you get. Hence, the OP's question – Jeff Holt Nov 29 '21 at 13:06
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.

- 195,001
- 40
- 254
- 396
-
Firstly,I do not understand what wrap-around means. Secondly, In the last point "We got in range at the first try" this means that if the number was -67865 it would have made the folowing calculation: first calculation -67865 + 65535 +1= -2329 second calculation: -2329 + 65535 + 1 = 63207 and now there is no third calculation because now it is in range, is this correct? – Tenko Nov 29 '21 at 15:09
-
@Tenko Wrap-around is what you get when going out of range on an unsigned integer type. It's what it sounds like, given `unsigned short x = 65535; x++;` you are guaranteed a wrap-around to zero. As opposed to signed integer overflow which is undefined behavior. The note about mathematical value means that among other things we shouldn't consider the maximum range of a variable during the calculation, only when we compare the result against the valid range. – Lundin Nov 29 '21 at 15:13
-
@Tenko "Wrap-around" is what a car's [odometer](https://en.wikipedia.org/wiki/Odometer) does when it rolls over from 99999 to 00000. Or what a clock does when it goes from 12:00 to 1:00. Or what a clock does if you're setting it backwards and it goes from 1:00 back to 12:00. The official term is "[Modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic)". – Steve Summit Nov 30 '21 at 13:21