How to cast or convert an unsigned int to int in C?
Asked Answered
D

7

29

My apologies if the question seems weird. I'm debugging my code and this seems to be the problem, but I'm not sure.

Thanks!

Dochandorrach answered 26/2, 2011 at 20:19 Comment(2)
The real question is what you want to do when/if the value in the unsigned int it out of the range that can be represented by a signed int. If it's in range, just assign it and you're done. If it's out of range, that'll give an unspecified result so you'll probably want to reduce it the right range first, or assign it to a larger signed type.Appear
Not unspecified, implementation-defined (C99 6.3.1.3§3). Otherwise I agree, and assigning to a larger signed int is the easiest solution.Campestral
S
36

It depends on what you want the behaviour to be. An int cannot hold many of the values that an unsigned int can.

You can cast as usual:

int signedInt = (int) myUnsigned;

but this will cause problems if the unsigned value is past the max int can hold. This means half of the possible unsigned values will result in erroneous behaviour unless you specifically watch out for it.

You should probably reexamine how you store values in the first place if you're having to convert for no good reason.

EDIT: As mentioned by ProdigySim in the comments, the maximum value is platform dependent. But you can access it with INT_MAX and UINT_MAX.

For the usual 4-byte types:

4 bytes = (4*8) bits = 32 bits

If all 32 bits are used, as in unsigned, the maximum value will be 2^32 - 1, or 4,294,967,295.

A signed int effectively sacrifices one bit for the sign, so the maximum value will be 2^31 - 1, or 2,147,483,647. Note that this is half of the other value.

Slowpoke answered 26/2, 2011 at 20:24 Comment(4)
Do you know what the max value for an unsigned is? and for an int?Dochandorrach
@Eric Brotto: It's going to depend on the system you're compiling for. Usually there's macros available for INT_MAX, UINT_MAX if you need to check. On most 32-bit systems, INT_MAX is going to be (2^31)-1 and UINT_MAX is (2^32)-1. Note that UINT_MAX cast as int will be -1.Allayne
"Usually" in the sense that the C standard requires them (for a hosted system).Pejorative
Actually these macros (residing in <limits.h> are required even on a freestanding (i.e., non-hosted) system.Regen
C
8

IMHO this question is an evergreen. As stated in various answers, the assignment of an unsigned value that is not in the range [0,INT_MAX] is implementation defined and might even raise a signal. If the unsigned value is considered to be a two's complement representation of a signed number, the probably most portable way is IMHO the way shown in the following code snippet:

#include <limits.h>
unsigned int u;
int i;

if (u <= (unsigned int)INT_MAX)
  i = (int)u; /*(1)*/
else if (u >= (unsigned int)INT_MIN)
  i = -(int)~u - 1; /*(2)*/
else
  i = INT_MIN; /*(3)*/
  • Branch (1) is obvious and cannot invoke overflow or traps, since it is value-preserving.

  • Branch (2) goes through some pains to avoid signed integer overflow by taking the one's complement of the value by bit-wise NOT, casts it to 'int' (which cannot overflow now), negates the value and subtracts one, which can also not overflow here.

  • Branch (3) provides the poison we have to take on one's complement or sign/magnitude targets, because the signed integer representation range is smaller than the two's complement representation range.

This is likely to boil down to a simple move on a two's complement target; at least I've observed such with GCC and CLANG. Also branch (3) is unreachable on such a target -- if one wants to limit the execution to two's complement targets, the code could be condensed to

#include <limits.h>
unsigned int u;
int i;

if (u <= (unsigned int)INT_MAX)
  i = (int)u; /*(1)*/
else
  i = -(int)~u - 1; /*(2)*/

The recipe works with any signed/unsigned type pair, and the code is best put into a macro or inline function so the compiler/optimizer can sort it out. (In which case rewriting the recipe with a ternary operator is helpful. But it's less readable and therefore not a good way to explain the strategy.)

And yes, some of the casts to 'unsigned int' are redundant, but

  • they might help the casual reader

  • some compilers issue warnings on signed/unsigned compares, because the implicit cast causes some non-intuitive behavior by language design

Converse answered 15/11, 2020 at 8:3 Comment(2)
Are you sure (unsigned int)INT_MIN is well-defined?Dahna
Yes. At least as long the compiler headers define INT_MIN in the way they should, that is, a signed integer with the most negative possible value. Conversion from negative signed integer to unsigned integer is well-defined and results in the bit pattern of the two's complement, always.Converse
M
6

Unsigned int can be converted to signed (or vice-versa) by simple expression as shown below :

unsigned int z;
int y=5;
z= (unsigned int)y;   

Though not targeted to the question, you would like to read following links :

Margay answered 26/2, 2011 at 20:28 Comment(1)
I think you meant to say "z = (unsigned int)y;" in the expression above. Since y is already an int, casting it to int is kind of pointless...Hairstyle
S
3

If you have a variable unsigned int x;, you can convert it to an int using (int)x.

Samson answered 26/2, 2011 at 20:23 Comment(0)
B
1

It's as simple as this:

unsigned int foo;
int bar = 10;

foo = (unsigned int)bar;

Or vice versa...

Biome answered 26/2, 2011 at 20:24 Comment(2)
The cast is redundant and ugly. Assignment inherently includes conversion in C for types where the assignment makes sense (and even for some where it doesn't). Casts usually serve just to cover up incorrect code.Naranjo
That's not true, this is actually a fairly common problem if you're checking to see if a certain amount of time has passed. Your interval should be an unsigned integer as it doesn't make sense for it to be signed, but time_t is always signed so it can represent dates older than 1970. If you don't do a cast when doing if ((now - then) > interval) the compiler will generate warnings.Scotism
K
1

If an unsigned int and a (signed) int are used in the same expression, the signed int gets implicitly converted to unsigned. This is a rather dangerous feature of the C language, and one you therefore need to be aware of. It may or may not be the cause of your bug. If you want a more detailed answer, you'll have to post some code.

Kinata answered 26/2, 2011 at 21:15 Comment(0)
M
0

Some explain from C++Primer 5th Page 35

If we assign an out-of-range value to an object of unsigned type, the result is the remainder of the value modulo the number of values the target type can hold.

For example, an 8-bit unsigned char can hold values from 0 through 255, inclusive. If we assign a value outside the range, the compiler assigns the remainder of that value modulo 256.

unsigned char c = -1; // assuming 8-bit chars, c has value 255

If we assign an out-of-range value to an object of signed type, the result is undefined. The program might appear to work, it might crash, or it might produce garbage values.

Page 160: If any operand is an unsigned type, the type to which the operands are converted depends on the relative sizes of the integral types on the machine.

... When the signedness differs and the type of the unsigned operand is the same as or larger than that of the signed operand, the signed operand is converted to unsigned.

The remaining case is when the signed operand has a larger type than the unsigned operand. In this case, the result is machine dependent. If all values in the unsigned type fit in the large type, then the unsigned operand is converted to the signed type. If the values don't fit, then the signed operand is converted to the unsigned type.

For example, if the operands are long and unsigned int, and int and long have the same size, the length will be converted to unsigned int. If the long type has more bits, then the unsigned int will be converted to long.

I found reading this book is very helpful.

Myriammyriameter answered 8/4, 2019 at 1:31 Comment(2)
"If we assign an out-of-range value to an object of signed type, the result is undefined. " - this is wrong, it is actually implementation-definedElectrograph
Also, this is a C question but you have quoted a C++ reference. C and C++ are different languagesElectrograph

© 2022 - 2024 — McMap. All rights reserved.