- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- About the company

Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
How to cast or convert an unsigned int to int in C?
My apologies if the question seems weird. I'm debugging my code and this seems to be the problem, but I'm not sure.

- 1 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. – Jerry Coffin Feb 26, 2011 at 20:23
- Not unspecified, implementation-defined (C99 6.3.1.3§3). Otherwise I agree, and assigning to a larger signed int is the easiest solution. – Gauthier Feb 18, 2014 at 10:39
7 Answers 7
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:
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:
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.
- Do you know what the max value for an unsigned is? and for an int? – Eric Brotto Feb 26, 2011 at 20:30
- 1 @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. – ProdigySim Feb 26, 2011 at 20:34
- 2 "Usually" in the sense that the C standard requires them (for a hosted system). – Jim Balter Feb 27, 2011 at 3:38
- Actually these macros (residing in <limits.h> are required even on a freestanding (i.e., non-hosted) system. – DevSolar Jul 11, 2021 at 16:15
Unsigned int can be converted to signed (or vice-versa) by simple expression as shown below :
Though not targeted to the question, you would like to read following links :
- signed to unsigned conversion in C - is it always safe?
- performance of unsigned vs signed integers
- Unsigned and signed values in C
- What type-conversions are happening?
- 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... – A. Levy Jun 1, 2011 at 15:50
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:
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
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
- Are you sure (unsigned int)INT_MIN is well-defined? – Dan Bechard Mar 17, 2021 at 7:11
- 1 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. – Pearly Mar 20, 2021 at 9:40
If you have a variable unsigned int x; , you can convert it to an int using (int)x .
It's as simple as this:
Or vice versa...
- 3 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. – R.. GitHub STOP HELPING ICE Feb 26, 2011 at 22:20
- 2 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. – Arran Cudbard-Bell May 26, 2014 at 12:59
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.

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.
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.

- "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-defined – M.M Nov 5, 2019 at 23:36
- Also, this is a C question but you have quoted a C++ reference. C and C++ are different languages – M.M Nov 5, 2019 at 23:37
Your Answer
Sign up or log in, post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service , privacy policy and cookie policy
Not the answer you're looking for? Browse other questions tagged c casting types int unsigned or ask your own question .
- The Overflow Blog
- Five Stack Exchange sites turned ten years old this quarter!
- “Move fast and break things” doesn’t apply to other people’s savings (Ep. 544)
- Featured on Meta
- We've added a "Necessary cookies only" option to the cookie consent popup
- Launching the CI/CD and R Collectives and community editing features for...
- The [amazon] tag is being burninated
- Temporary policy: ChatGPT is banned
- Staging Ground Beta 1 Recap, and Reviewers needed for Beta 2
Hot Network Questions
- Create number 985 using 1 3 5 7 9
- Plotting a kidney shape in Mathematica
- Does every US state set its standard deduction to match the federal one? Why?
- Distrust versus mistrust
- Has anyone measured what a high-impedance pin looks like?
- In England, why are some high schools called hospitals?
- Google maps for Space exploration
- Box character doesn't display properly in linux terminal
- Concrete base for parcel box
- How did theorists determine that the atmosphere attenuates enough to support unpowered orbits?
- Forced to pay a customs fee for importing a used wedding dress into the Netherlands. Is there a way to avoid paying?
- Does Hooke's Law apply to all springs?
- Does the attacker need to be on the same network to carry out a deauthentication attack?
- Checksum of secret data
- Audio interface outputs lower volume from the monitor outputs
- Why did Windows 3.0 fail in Japan?
- Temperature Pressure Release (TPR) Valve Leaking
- Options for "Cancel this operation?" are "Cancel" and "Yes"; what would be better wording for customers in a hurry?
- Earn CC flight miles by paying rent?
- Properties of categorical zeta function
- Can there be a repulsion between an electron beam and a proton beam depending on the beam's velocities?
- How would zombies affect trench warfare?
- how to numbered cells in longtable with latex like this?
- What laws would Jesus be breaking if he were to turn water into wine today?
Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .
- Windows Programming
- UNIX/Linux Programming
- General C++ Programming
- Unsigned int to int and vice-versa
Unsigned int to int and vice-versa

- Data professional
- Security professional
- Software dev
Contact Sales
Loading form...
If this message remains, it may be due to cookies being disabled or to an ad blocker.

Converting unsigned integers to signed integers can lead to hidden bugs
It’s no big surprise that strange things can happen during conversions of any kind, and working with unsigned-to-signed integers is no exception. But these types of conversions are especially tricky because they can lead to bugs that aren’t always noticeable and may end up affecting your C++ code. In order to better understand what we’re dealing with here, let’s first take a look at the bug in action, and then a possible solution for fixing the problem.
What can go wrong
In C++ there are two types of integer variables known as signed and unsigned . As briefly mentioned, when you convert large, unsigned integers to signed versions, weird things can (and often do) happen. With the fundamental type int , if you don’t add any additional keywords, you get a signed integer by default. On the other hand, adding the unsigned modifier ( unsigned int ), gets you an unsigned integer.
Unsigned integers are common when you have C++ code that interoperates with the STL library. In fact, if you want to get the item count in a std::vector, the vector’s size method returns a value of a type equivalent to size_t , which is an unsigned integer.
You can have other portions of your C++ code that may require quantities expressed in the form of signed integers. For example, many Win32 APIs (or the ATL’s CString class) expect length and size parameters in the form of a (signed) int. So, at some point in your code, you’ll end up with an integer quantity expressed as an unsigned integer (e.g. a size_t-value from an STL container) and you’ll have to pass it to APIs or class methods, expecting the same quantity but expressed in the form of a signed integer. This means that you have to convert from an unsigned integer to a signed integer . And that’s when things get tricky.
To get a better idea, consider the following compilable C++ code snippet:
In this code, the line marked with an asterisk, the value of a variable ‘u’ of type size_t, which is an unsigned integer, is converted to a signed integer stored in the variable ‘i’. If you compile this code with Microsoft’s Visual C++ compiler in 32-bit mode, and at a reasonably high warning level ( /W4 ), you’ll get a warning-free (and error-free) output. Seems like everything’s fine, right? Not exactly…
If you run that code, here’s what you’ll get:
As you can see, we started with a (positive) unsigned integer (3GB). after the conversion from unsigned to signed integer, you end up with a negative value! This is due to the fact that while 3,221,225,472 (3GB) is a value that can be safely stored in a 32-bit unsigned integer, the same value exceeds the maximum positive value that can be stored in a signed 32-bit integer (this value being 2,147,483,647). Of course, getting 3GB converted to a negative value of -1GB doesn’t make sense in this context.
Now, if you imagine such unsigned-to-signed integer conversions immersed in more complex code bases, with several computations that add up, you can figure out what kind of subtle bugs can hide in your C++ code.
Checking integer limits before converting
To avoid these bugs, we can define a custom function for the conversion from unsigned to signed integers. Inside the body of this function, we can check if the input unsigned value is too big for a variable of type int. In this case, instead of continuing with a bogus conversion, we’ll throw a C++ exception to signal the conversion error.
The prototype of this function can look like this:
Inside the function, the first thing we need to do is to check if the value of the unsigned variable ‘u’ can be safely stored in a signed integer, without being converted to a negative bogus number.
In pseudo code, the logic looks like this:
So, how can you get the maximum value for a variable of type int?
Well, there’s a standard component available in the C++ standard library called std::numeric_limits . This is a class template that can be used to query various properties of arithmetic types, including int. Basically, you pass the name of the type as the T template parameter of numeric_limits< T >, and then you can call the class’ methods to query the desired properties. For example, “numeric_limits<T>:: max() ” will return the maximum value of the type T. Since we want the maximum value that can be stored in a variable of type int, we can simply invoke “numeric_limits< int >::max()”.
So, we can use this C++ code to prevent bogus unsigned to signed conversions:
However, note that the Microsoft Visual C++ compiler emits a warning complaining about a signed/unsigned mismatch regarding the use of “operator >” in the ‘if’ condition. In fact, ‘u’ is a variable of type size_t, which is unsigned; instead, the value returned by the numeric_limits::max call is of type int, which is signed.
We can easily fix that warning with the addition of a simple static_cast:
Now, if you replace the “int i = u;” statement with a call to the previously defined SizeToInt() function, an exception will be thrown, instead of storing a bogus negative value in the destination int variable. It’s also important to note that if the previous line is replaced using a more modern C++11’s brace-init syntax “int i{u};” the MSVC compiler emits an explicit error:
Again, the use of our custom SizeToInt conversion function can fix that compiler error.
Neutralizing Windows’s max preprocessor macro
If we want this code to be usable in Windows C++ applications, we need to add a final touch to our SizeToInt function. Note that if you simply try to #include the main Windows SDK header <Windows.h> , the function’s code will generate several apparent weird compile-time errors. These weren’t present previously, they just popped up after including <Windows.h> -- so, what’s problem?
The problem is that Windows SDK headers define a custom max preprocessor macro (a matching min macro is defined as well), which conflicts with the C++’s std::numeric_limits<T>::max call, generating compiler errors. To prevent this conflict, you can use an additional pair of parentheses in the numeric_limits::max call, like this: “ ( std::numeric_limits<int>::max ) ()”. By doing this, the Windows’s max preprocessor macro won’t interfere with the numeric_limits::max method call.
So, the final implementation of our SizeToInt function looks like this:
Working with 64-bit builds
I developed the previous scenario assuming 32-bit builds with the Microsoft Visual C++ compiler. But interesting things can happen happen in 64-bit builds, too. In this context, the size_t type is 64-bit wide, but the int type is still 32 bits. If you have a 5GB value stored in a variable of type size_t and convert that to an int, you end up with a 1GB value. When this happens, a large 64-bit unsigned integer number (5GB) is converted to a positive, but smaller, signed 32-bit integer (1GB). Again, this can lead to subtle bugs in code, with “magic” numbers popping up in a meaningless way, and more complex calculations leading to bogus results.
If an unsigned integer can’t be meaningful when converted to a signed one, it’s better throwing an exception than having subtle bugs hiding in code. Note that the previously developed SizeToInt function also works fine in 64-bit builds.
As you can see, even assuming the same number of bits used to store an integer, signed and unsigned integers have different positive value limits. Converting a large positive unsigned number to a signed one can lead to bogus results (like negative numbers!) and hard-to-find bugs. The key point of our custom conversion function is to check the value of the input size_t unsigned variable, and then throwing an exception if this value is too big to be stored in a variable of type (signed) int. It’s essential to note that the conversion is only done when it’s meaningful. Having an exception thrown is certainly better than hard-to-spot bugs that pop up from big, unsigned integer numbers converted to negative (or smaller) signed integers.
Ready to learn more? Check out my courses here .

Contributor
Giovanni dicanio.
Giovanni Dicanio is a computer programmer specializing in C, C++ and the Windows OS. He is a Pluralsight author and Visual C++ MVP, with computer programming experience dating back to the glorious Commodore 64 and Commodore Amiga 500 golden days. Giovanni enjoys several aspects of development: from design to actual code writing, to debugging and code reviews. Feel free to contact him at giovanni.dicanio AT gmail.com or visit his website . Besides programming and course authoring, he enjoys helping others on forums and communities devoted to C++.
Ready to skill up your entire team?
With your pluralsight plan, you can:, with your 30-day pilot, you can:.
- Access thousands of videos to develop critical skills
- Give up to 10 users access to thousands of video courses
- Practice and apply skills with interactive courses and projects
- See skills, usage, and trend data for your teams
- Prepare for certifications with industry-leading practice exams
- Measure proficiency across skills and roles
- Align learning to your goals with paths and channels
- Help Center
- IP Allowlist
- Download Pluralsight
- Skills Plans
- Partner with Pluralsight
- Affiliate Partners
- Pluralsight One
- Public Sector
Sign up with your email to join our mailing list.

- Terms of Use
- Privacy Notice
- Modern Slavery Statement
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Conversions from unsigned integral types
- 2 minutes to read
- 8 contributors
When an unsigned integer is converted to an integer or floating-point type, if the original value is representable in the result type the value is unchanged.
When the compiler converts an unsigned integer to an integer of greater size, the value is zero-extended. When converted to an integer of smaller size, the high-order bits are truncated. The result is interpreted using the result type, as shown in this example:
When the compiler converts an unsigned integer to a floating-point type, if the original value isn't representable exactly in the result type, the result is the next higher or lower representable value.
See Storage of basic types for information about the sizes of integral and floating-point types.
Microsoft Specific
In the Microsoft compiler, unsigned (or unsigned int ) and unsigned long are distinct but equivalent types. Conversion of an unsigned int value proceeds in the same way as conversion of an unsigned long .
END Microsoft Specific
The following table summarizes conversions from unsigned integral types.
Table of conversions from unsigned integral types
Assignment conversions
Submit and view feedback for
Additional resources
- Michael Barr
Nigel Jones
- Posts by Category
- Newsletter Signup

A tutorial on signed and unsigned integers
Wednesday, August 5th, 2009 by Nigel Jones
One of the interesting things about writing a blog is looking at the search terms that drive traffic to your blog. In my case, after I posted these thoughts on signed versus unsigned integers, I was amazed to see how many people were ending up here looking for basic information concerning signed and unsigned integers. In an effort to make these folks visits more successful, I thought I’d put together some basic information on this topic. I’ve done it in a question and answer format.
All of these questions have been posed to a search engine which has driven traffic to this blog. For regular readers of this blog looking for something a bit more advanced, you will find the last section more satisfactory.
Are integers signed or unsigned?
A standard C integer data type (‘int’) is signed. However, I strongly recommend that you do not use the standard ‘int’ data type and instead use the C99 data types. See here for an explanation.
How do I convert a signed integer to an unsigned integer?
This is in some ways a very elementary question and in other ways a very profound question. Let’s consider the elementary issue first. To convert a signed integer to an unsigned integer, or to convert an unsigned integer to a signed integer you need only use a cast. For example:
Actually in many cases you can dispense with the cast. However many compilers will complain, and Lint will most certainly complain. I recommend you always explicitly cast when converting between signed and unsigned types.
OK, well what about the profound part of the question? Well if you have a variable of type int, and it contains a negative value such as -9 then how do you convert this to an unsigned data type and what exactly happens if you perform a cast as shown above? Well the basic answer is – nothing. No bits are changed, the compiler just treats the bit representation as unsigned. For example, let us assume that the compiler represents signed integers using 2’s complement notation (this is the norm – but is *not* mandated by the C language). If our signed integer is a 16 bit value, and has the value -9, then its binary representation will be 1111111111110111. If you now cast this to an unsigned integer, then the unsigned integer will have the value 0xFFF7 or 65527 10 . Note however that you cannot rely upon the fact that casting -9 to an unsigned type will result in the value 0xFFF7. Whether it does or not depends entirely on how the compiler chooses to represent negative numbers.
What’s more efficient – a signed integer or an unsigned integer?
The short answer – unsigned integers are more efficient. See here for a more detailed explanation.
When should I use an unsigned integer?
In my opinion, you should always use unsigned integers, except in the following cases:
- When the entity you are representing with your variable is inherently a signed value.
- When dealing with standard C library functions that required an int to be passed to them.
- In certain weird cases such as I documented here .
Now be advised that many people strongly disagree with me on this topic. Naturally I don’t find their arguments persuasive.
Why should I use an unsigned integer?
Here are my top reasons:
- By using an unsigned integer, you are conveying important information to a reader of your code concerning the expected range of values that a variable may take on.
- They are more efficient .
- Modulus arithmetic is completely defined .
- Overflowing an unsigned data type is defined, whereas overflowing a signed integer type could result in World War 3 starting.
- You can safely perform shift operations.
- You get a larger dynamic range.
- Register values should nearly always be treated as unsigned entities – and embedded systems spend a lot of time dealing with register values.
What happens when I mix signed and unsigned integers?
This is the real crux of the problem with having signed and unsigned data types. The C standard has an entire section on this topic that only a compiler writer could love – and that the rest of us read and wince at. Having said that, it is important to know that integers that are signed get promoted to unsigned integers. If you think about it, this is the correct thing to happen. However, it can lead to some very interesting and unexpected results. A number of years ago I wrote an article “A ‘C’ Test:The 0x10 Best Questions for Would-be Embedded Programmers” that was published in Embedded Systems Programming magazine. You can get an updated and corrected copy at my web site . My favorite question from this test is question 12 which is reproduced below – together with its answer: What does the following code output and why?
This question tests whether you understand the integer promotion rules in C – an area that I find is very poorly understood by many developers. Anyway, the answer is that this outputs “> 6”. The reason for this is that expressions involving signed and unsigned types have all operands promoted to unsigned types. Thus -20 becomes a very large positive integer and the expression evaluates to greater than 6. This is a very important point in embedded systems where unsigned data types should be used frequently (see reference 2). If you get this one wrong, then you are perilously close to not being hired.
This is all well and good, but what should one do about this? Well you can pore over the C standard, run tests on your compiler to make sure it really does conform to the standard, and then write conforming code, or you can do the following: Never mix signed and unsigned integers in an expression. I do this by the use of intermediate variables. To show how to do this, consider a function that takes an int ‘a’ and an unsigned int ‘b’. Its job is to return true if b > a, otherwise it returns false. As you shall see, this is a surprisingly difficult problem… To solve this problem, we need to consider the following:
- The signed integer a can be negative.
- The unsigned integer b can be numerically larger than the largest possible value representable by a signed integer
- The integer promotion rules can really screw things up if you are not careful.
With these points in mind, here’s my stab at a robust solution
Is this a lot of work – yes. Could I come up with a more compact implementation that is guaranteed to work for all possible values of a and b – probably. Would it be as clear – I doubt it. Perhaps regular readers of this blog would like to take a stab at producing a better implementation?
Tags: signed , unsigned
This entry was posted on Wednesday, August 5th, 2009 at 11:32 am and is filed under General C issues . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.
43 Responses to “A tutorial on signed and unsigned integers”
I'm pretty sure that the C99 types are specified as twos complement in the standard. Of course, the format of plain old int/signed int are still left unspecified.
What is the difference between "signed int" and "int"? According to section A8.2 of the ANSI C standard – "The signed specifier is useful for forcing char objects to carry a sign; it is permissible but redundant with other integral types."Is it different in C99?
Is it really true that “No bits are changed” when converting signed to unsigned? According to section 6.3.1.3 of C99 standard — “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”. I think that it’s true only for computers using two’s complement representation for signed but not for computers using one’s complement.
Interesting. I’ve never worked on a 1’s complement machine. However thinking about it, you must be correct that it’s only on a 2’s complement machine that nothing changes.
thanks for your beneficial article
Thank you for realy rewarding article. I have to say I didn´t know a lot mentioned facts. Few days ago I came upon a problem which I can´t solve even with new knowledge from the article. May be somebody could try to explain it to me.
unsigned short a = 0xFFF8; signed short result;
result = ((((signed short) a)*7)+8)/16;
I was expextiong the result -3 but it was 28669!!! No clue why.
((signed short) 0xFFF8) is undefined if bitsof(signed short) <= 16 !!
See 6.3.1.3 Part 3
6.3.1.3 Signed and unsigned integers 1 When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged. 2 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) ————————————————————— 3 Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised. —————————————————————
What compiler did you use? When I try this in Visual Studio Express 2010, I get the result that you expected. A possible reason could be that short is greater than 16 bits in your environment.
virThat is correct, just put “int” instead of “short” in David’s expression and you will get 28869. That’s because in his enonment “short” has 32bits. And that means that as long as result is of expression is in value range from “0” to ” 2 147 483 647″ number, effect is like there is no propagation. FFF8 does not convert to negative number because it can stand like positive value on 32 bit size of value;
Signed type value ranges (32 bit size): FFF8 q) printf (” p is larger than q”); else // cannot be even, obvious reasons. printf (“p is is smaller than q”);
Just for this example I assumed that int and long are types that have different bit size (unsigned int = 16 bit, signed long = 32). So in this example 15U (unsigned int) propagates to larger bit type that is signed long int. Lets visualize : unsigned int signed long 33016 15 1000 0000 1111 1000 0000 0000 0000 00000000 0000 0000 1111 After propagation, one method: ————————————————
15 0000 0000 0000 0000 1111 1111 1111 0110 0000 000 0000 0000 0000 0000 0000 1111
In this method we see logical expending of bits as we call it (not sure what is correct term), by adding zeros on left side. So unsigned int value = 33016 is larger than signed long int =15. Eventual other method: ———————- unsigned int signed long 33016 15 1000 0000 1111 1000 0000 0000 0000 00000000 0000 0000 1111
————————————————
-32520 15 1111 1111 1111 1111 1000 0000 1111 1000 0000 000 0000 0000 0000 0000 0000 1111
This method uses Arithmetic expanding to right by expanding negative sign 1, when left-most significant bit of value with lower number of bit propagates to value in higher number of bits . My question is, is it possible that different architectures of computer could contribute to sometimes positive values propagate to negative values because of different instructions that “expand” bits are implemented or is that concern of the past? I red that information in book Programing in C , second edition. Sorry, my English is not superb, hope that I was understandable/readable.
There’s no need to apologize for your English. I’m always in awe of the English language proficiency of the readers of this blog. Thanks for your post.
I’m pretty sure “int” and “signed int” are exactly the same type in C. In C++, if I try to overload on int and signed int, g++ gives me a redefinition error. I can even define main as “signed main(signed, char**){}” (in C or C++).
This does not happen for “char”, though — “char”, “signed char”, and “unsigned char” are three distinct (and, in C++, overloadable) types. (And if I try to define main using “int main(int, signed char**)”, gcc warns that it’s wrong.)
I agree and have updated the post to correct this. Thanks for pointing it out.
There is one case where “int” and “signed int” are not synonymous – bitfields: typedef struct { int F : 16; } S;
The compiler is allowed to treat S.F as unsigned (or signed – it gets to pick). You can force it to be signed by saying: typedef struct { signed int F : 16; } S;
Some compilers allow you to specify with the default for an “int” is signed or unsigned on the command line.
I have a question to bit fields. Is there any practical need of using signed bitfield element? We had issues when we were using single bits:
typedef struct A { int a:1; int b:1; … }
Some MISRA rule violated (can’t remember which one) and actually in case of signed, this was either -1 or 0 if I remember well. So for single bit, I would recommend to use always unsigned type.
Whilst the behavior of bit fields in general is terribly undefined, the behavior of signed bit fields is downright appalling. I feel quite confident in saying that in 30+ years of doing this I have never used a signed bit field. Don’t do it!
Another version:
bool foo(int a, unsigned int b) { if (a c; /* Now I’m comparing the same data types */ }
Really your information is useful… good explanation good examples
If you really want to get down to the nitty gritty bitty, here’s the rhyme and reason of 2’s compliment as the way to represent negative numbers, why it works, what it is, and the way computers use this trick to keep circuitry simple with add/subtract regardless of register size/type… http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Hey there! I want to print counter increments and decrements which varies from -120 to 120, but when i decrement it below zero , it start decrementing from 65536. Please help me.
Clearly you’ve specified your counter to be unsigned. Declare it to be signed and life should be good.
Another possibility is that you are using a signed integer but using printf (or similiar) to view the value and using “%u” as the format specifier. It might be working right but the display is wrong ///
The issue gets even more sticky in the first foo example if a is defined as an unsigned char instead of an unsigned int. It seems that unsigned char promotes to signed int, which is counter intuitivive. This means the code:
unsigned char a, b;
x += (a-b)/4;
will take the difference between a and b as a signed value and do the right thing while if a and b are signed you get garbage if a < b.
I’m confused as to the terminology. I always thought that declaring a variable as unsigned meant it held only positive values, and signed variables could hold both positive and negative values. So if x and y are unsigned int16 with x= 0, y= 1, then x – y = 65535, not -1.
I also thought that casting a variable from signed to unsigned and visa versa only produces a valid result for a variable that contain a positive number. When did the compilers start trying to cast an unsigned value with the MSbit = 1 as a negative number??
There is something basic that I am missing.
[…] that might be unreliable in the signed case, including bitwise operations such as shifting. This blog post talks more about signed vs […]
void foo(void) { unsigned int a = 6; int b = -20; (a+b > 6) ? puts(“> 6″) : puts(” 6) ? puts(“> 6”) : puts(“<= 6"); }
output: <=6
So, what is the case when I used 'short' datatype?
for the last code you wrote how about this
bool foo(int a, unsigned int b) { bool res;
if (a < 0) { res = true; /* If a is negative, it must be less than b */ } else { res = ( ( (unsigned int) a )<( b ) ); } return res; }
#include int main() { unsigned long int=-1; printf(“%d”,i); getch(); }
/* can any tell me the output of the above code and the reason why it is so ?? i am getting answer as -1 itself . i am not getting why unsigned int is printing me the negative value */
Because you’re telling printf to treat its argument as signed. If you want to print an unsigned integer you should use printf(“%u”,i); Note that because you have defined i as a long, then you should really tell printf the same thing and so printf(“%lu”,i); is more robust / portable.
tell error please
#include int main() { int i=-1; unsigned int j=1; if(i>j) printf(“greater i”); else printf(“greater j”);
return 0; }
output: greater i
In an expression involving signed and unsigned integers, the signed integers get promoted to unsigned. Since -1 usually equals 0xFFFF on 16 bit machines, the if statement become if (0xFFFF > 1) – which it is. The integer promotion rules can be quite complicated and so it’s worth your time learning about them.
#include #include int main() { int n,a=0,z,i,m,h; a=pow(10,4); int x; printf(“\n ENTER THE NUMBER \n”); scanf(“%d”,&n); printf(“\n NUMBER ENTERED BY YOU =%d”,n); z=n; x= log10(n); printf(“no of digits = %d”,x+1); for(a=0;n>0;x–) { m=n%10; n=n/10; h=pow(10,x); a=a+(h*m);
printf(“\na=%d”,a);
if(a==z) {printf(“\npalindrome\n”); } else {printf(“\nnot a palindrome\n”); }
h=999 when x=3 and h=99999 when x=5 in code blocks
What’s your point?
#include #include int main() { char str[7]=”work it”; printf(“%s”,str); return 0; }
output work it( so from where ‘(‘ is coming
I’m not sure of the point of your comment. Obviously the array str[] isn’t big enough to hold the string “work it” as you need space for the terminating nul. What will get printed depends upon how the strings are organised in memory. Printf will keep outputting characters until it hits a nul.
Sir , a question has been bugging me for a quite some time now , i want to ask if i write signed int a = -1 and usngiend int b = -1 , What i saw is they have same bit pattern , i want to ask , does a number representation depends on the negative sign (-) or it depends on whether i have assigned it the type signed or unsigned . Also if as my resluts have shown me , that no matter if it is unsigned type or signed type , it will always be stored in 2’s complemet way , then why do we need two different type, If i write signed int a = -1 , then ` -1` in 2’s complement form is 11111111 11111111 11111111 11111111 and then when i use %d to interpret it it prints -1 and %u , it prints 4294967295 and when i write signed int a = 2 , it prints 2 when i use %d and also when i use %u . If 2 would be in two’s complement it would be 11111111 11111111 11111111 11111101 , and then it would be a very diffr answer , what i really want to ask is when does 2’s complement happen is it depend on – sign or it happens for every integer if type is signed int which must not be the case here.
// This extended example demonstrates the following: // 1. both (a+b) 6 are true at the same time — // the ‘>’ operator uses 4294967279 unsigned form of the signed -17 value for comparison, // because at least one of its operands are unsigned, // 2. a small negative value and its corresponding big positive value is represented // with the same value in memory, // 3. printf %d and %u conversion specifiers prints memory value either in signed or unsigned form // regardless of the type of the input number, // 4. comparing constant numbers instead of expressions with different signedness are compared // by their unsigned values, // 5. short and char typed values are promoted to int type before comparison — // “”” // If an int can represent all values of the original type // (as restricted by the width, for a bit-field), // the value is converted to an int; otherwise, it is converted to an unsigned int. // These are called the integer promotions. // All other types are unchanged by the integer promotions. // “”” (C standard, 2011, 6.3.1.1.). // // ((a+b) 6) = true (1.) // a = 3 (0x00000003) // b = -20 (0xffffffec) // a+b %d = -17 (0xffffffef) (2.) (3.) // a+b %u = 4294967279 (0xffffffef) // (int)(a+b) %d = -17 (0xffffffef) // (int)(a+b) %u = 4294967279 (0xffffffef) // (unsigned int)(a+b) %d = -17 (0xffffffef) // (unsigned int)(a+b) %u = 4294967279 (0xffffffef) // 6 = 6 (0x00000006) // -1 = -1 (0xffffffff) // -2 = -2 (0xfffffffe) // (-2 < -1) = true // ( 18446744073709551610lu < ((long) -1)) = true (4.) // (((unsigned int) 4294967279) < ((int) -1)) = true // (((unsigned short) 65530) < ((short) -1)) = false (5.) // (((unsigned char) 250) < ((char) -1)) = false // 18446744073709551610 = 18446744073709551610 (0xfffffffffffffffa) // 4294967279 = 4294967279 (0x00000000ffffffef) // 65530 = 65530 (0x000000000000fffa) // 250 = 250 (0x00000000000000fa) // (char)-1 %hhd = -1 (0xff) // (char)-1 %hhu = 255 (0xff) // (short)-1 %hd = -1 (0xffff) // (short)-1 %hu = 65535 (0xffff) // sizeof(long) = 8 // sizeof(int) = 4 // sizeof(short) = 2 // sizeof(char) = 1
#include "stdio.h"
void main() { unsigned int a = 3; int b = -20;
printf("((a+b) < -1) = %10s\n", ((a+b) 6) = %10s”, ((a+b) > 6 ? “true” : “false”)); printf(“%38s\n”, “(1.)”); printf(“a = %10d (0x%08x)\n”, a, a); printf(“b = %10d (0x%08x)\n”, b, b); printf(“a+b %%d = %10d (0x%08x)”, a+b, a+b); printf(“%30s\n”, “(2.) (3.)”); printf(“a+b %%u = %10u (0x%08x)\n”, a+b, a+b); printf(“(int)(a+b) %%d = %10d (0x%08x)\n”, (int)(a+b), (int)(a+b)); printf(“(int)(a+b) %%u = %10u (0x%08x)\n”, (int)(a+b), (int)(a+b)); printf(“(unsigned int)(a+b) %%d = %10d (0x%08x)\n”, (unsigned int)(a+b), (unsigned int)(a+b)); printf(“(unsigned int)(a+b) %%u = %10u (0x%08x)\n”, (unsigned int)(a+b), (unsigned int)(a+b)); printf(“6 = %10d (0x%08x)\n”, 6, 6); printf(“-1 = %10d (0x%08x)\n”, -1, -1); printf(“-2 = %10d (0x%08x)\n”, -2, -2); printf(“(-2 < -1) = %10s\n", (-2 < -1 ? "true" : "false")); printf("( 18446744073709551610lu < ((long) -1)) = %s", ((18446744073709551610lu < ((long)-1)) ? "true" : "false")); printf("%22s\n", "(4.)"); printf("(((unsigned int) 4294967279) < ((int) -1)) = %s\n", ((((unsigned int)4294967279) < ((int)-1)) ? "true" : "false")); printf("(((unsigned short) 65530) < ((short) -1)) = %s", ((((unsigned short)65530) < ((short)-1)) ? "true" : "false")); printf("%21s\n", "(5.)"); printf("(((unsigned char) 250) < ((char) -1)) = %s\n", ((((unsigned char)250) < ((char)-1)) ? "true" : "false")); printf("18446744073709551610 = %20lu (0x%016lx)\n", 18446744073709551610lu, 18446744073709551610lu); printf("4294967279 = %20lu (0x%016lx)\n", 4294967279, 4294967279); printf("65530 = %20lu (0x%016lx)\n", 65530, 65530); printf("250 = %20lu (0x%016lx)\n", 250, 250); printf("(char)-1 %%hhd = %10hhd (0x%hhx)\n", (char)-1, (char)-1); printf("(char)-1 %%hhu = %10hhu (0x%hhx)\n", (char)-1, (char)-1); printf("(short)-1 %%hd = %10hd (0x%hx)\n", (short)-1, (short)-1); printf("(short)-1 %%hu = %10hu (0x%hx)\n", (short)-1, (short)-1); printf("sizeof(long) = %d\n", sizeof(long)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(short) = %d\n", sizeof(short)); printf("sizeof(char) = %d\n", sizeof(char)); }
To each his own, but i think foo’s intent is perfectly clear as a one-liner.
bool foo1(int a, unsigned int b) { return (a < 0) || ((unsigned int) a < b); }
This on the other hand…
bool foo2(int a, unsigned int b) { if (b > (unsigned int) INT_MAX) return true; unsigned int x = (unsigned int) a - (unsigned int) INT_MIN; unsigned int y = (unsigned int) a - b; return x < y; }
By the way, the site cppinsights shows nicely what the compiler internally uses, aka what is promoted to what. The example code results in the following:
unsigned int a = 6; int b = -20; int c = static_cast(a + static_cast(b));
https://cppinsights.io/s/181eb635
You say “Note however that you cannot rely upon the fact that casting -9 to an unsigned type will result in the value 0xFFF7. Whether it does or not depends entirely on how the compiler chooses to represent negative numbers.”
That is wrong. If int has 16 bits, casting -9 to int will always result in the value FFF7, irrespective of how negative numbers are represented. The point is that if the architecture uses 1s-complement or sign and magnitude, then the cast is bit altering. If the architecture is 2’s-complement then it is not.
“If int has 16 bits, casting -9 to int will always result in the value FFF7”: I meant, if int has 16 bits, casting -9 to unsigned int will always result in the value FFF7.
Leave a Reply
Name (required)
Mail (will not be published) (required)
XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
Stack Overflow

Nigel Jones is an embedded systems consultant with over 20 years of experience designing electronic circuits and firmware. ( full bio )
- Contact Nigel
- Articles on Embedded Systems
- Embedded C Coding Standard
- Embedded Software Training in a Box
- Embedded Systems Design, Consulting, and Expert Witness Services
Recent Posts
- EEPROM Wear Leveling
- Hamming distances
- Peak detection of a time series
- Boeing Dreamliner ‘Bug’
- Freescale customer service
- Shifting Styles
- The engineering – marketing divide
- Replacing nested switches with multi-dimensional arrays of pointers to functions
- Idling along, (or what to do in the idle task)
Recent Comments
- mattallen37 on Checking the fuse bits in an Atmel AVR at run time
- Simon Packer on An open letter to the developers of the MPLAB IDE
- Beginner on Checking the fuse bits in an Atmel AVR at run time
- Boris Oriet on Median filtering
- Algorithms (16)
- Coding Standards (23)
- Compilers / Tools (25)
- Consulting (14)
- Effective C/C++ (13)
- Efficient C/C++ (20)
- Firmware Bugs (12)
- General C issues (49)
- Hardware (22)
- Low Power Design (7)
- Minimizing memory consumption (3)
- Publications (12)
- RTOS Multithreading (2)
- Uncategorized (32)
- July 2017 (1)
- June 2017 (1)
- September 2015 (1)
- May 2015 (1)
- March 2015 (1)
- February 2015 (1)
- November 2014 (1)
- April 2014 (1)
- March 2014 (1)
- April 2013 (1)
- February 2013 (1)
- January 2013 (1)
- December 2012 (1)
- July 2012 (2)
- June 2012 (2)
- March 2012 (1)
- February 2012 (2)
- December 2011 (2)
- September 2011 (2)
- August 2011 (1)
- June 2011 (1)
- May 2011 (1)
- March 2011 (1)
- February 2011 (4)
- January 2011 (1)
- December 2010 (2)
- November 2010 (3)
- October 2010 (2)
- September 2010 (2)
- August 2010 (8)
- June 2010 (2)
- May 2010 (2)
- April 2010 (1)
- March 2010 (3)
- February 2010 (4)
- January 2010 (2)
- December 2009 (18)
- November 2009 (3)
- October 2009 (7)
- September 2009 (8)
- August 2009 (4)
- July 2009 (4)
- June 2009 (4)
- May 2009 (4)
- April 2009 (5)
- March 2009 (5)
- February 2009 (6)
- January 2009 (4)
- December 2008 (3)
- November 2008 (3)
- October 2008 (1)
- September 2008 (2)
- August 2008 (3)
- July 2008 (1)
- June 2008 (3)
- May 2008 (2)
- April 2008 (1)
- February 2008 (1)
- January 2008 (3)
- August 2007 (2)
- July 2007 (1)
- June 2007 (2)
- May 2007 (2)
- April 2007 (1)
- March 2007 (1)
- December 2006 (3)
- November 2006 (2)
- October 2006 (2)
- September 2006 (5)
Embedded Gurus - Experts on Embedded Software
website by Accent Interactive

C in a Nutshell by Peter Prinz, Tony Crawford
Get full access to C in a Nutshell and 60K+ other titles, with a free 10-day trial of O'Reilly.
There are also live events, courses curated by job role, and more.
Chapter 4. Type Conversions
In C, operands of different types can be combined in one operation. For example, the following expressions are permissible:
When the operands have different types, the compiler tries to convert them to a uniform type before performing the operation. In certain cases, furthermore, you must insert type conversion instructions in your program. A type conversion yields the value of an expression in a new type, which can be either the type void (meaning that the value of the expression is discarded: see " Expressions of Type void " in Chapter 2 ), or a scalar type—that is, an arithmetic type or a pointer. For example, a pointer to a structure can be converted into a different pointer type. However, an actual structure value cannot be converted into a different structure type.
The compiler provides implicit type conversions when operands have mismatched types, or when you call a function using an argument whose type does not match the function’s corresponding parameter. Programs also perform implicit type conversion as necessary when initializing variables or otherwise assigning values to them. If the necessary conversion is not possible, the compiler issues an error message.
You can also convert values from one type to another explicitly using the cast operator (see Chapter 5 ):
In the following example, the cast operator causes the division of one integer variable by another to be performed as a floating-point operation:
Because the cast operator has precedence over division, the value of sum in this example is first converted to type double . The compiler must then implicitly convert the divisor, the value of count , to the same type before performing the division.
You should always use the cast operator whenever there is a possibility of losing information, as in a conversion from int to unsigned int , for example. Explicit casts avoid compiler warnings, and also signpost your program’s type conversions for other programmers. For example, using an explicit cast to void when you discard the return value of a function serves as a reminder that you may be disregarding the function’s error indications.
To illustrate the implicit type conversions that the compiler provides, however, the examples in this chapter use the cast operator only when it is strictly necessary.
Conversion of Arithmetic Types
Type conversions are always possible between any two arithmetic types , and the compiler performs them implicitly wherever necessary. The conversion preserves the value of an expression if the new type is capable of representing it. This is not always the case. For example, when you convert a negative value to an unsigned type, or convert a floating-point fraction from type double to the type int , the new type simply cannot represent the original value. In such cases the compiler generally issues a warning.
Hierarchy of Types
When arithmetic operands have different types, the implicit type conversion is governed by the types’ conversion rank . The types are ranked according to the following rules:
Any two unsigned integer types have different conversion ranks. If one is wider than the other, then it has a higher rank.
Each signed integer type has the same rank as the corresponding unsigned type. The type char has the same rank as signed char and unsigned char .
The standard integer types are ranked in the order:
Any standard integer type has a higher rank than an extended integer type of the same width. (Extended integer types are described in the section “Integer Types with Exact Width (C99)” in Chapter 2 .)
Every enumerated type has the same rank as its corresponding integer type (see " Enumerated Types " in Chapter 2 ).
The floating-point types are ranked in the following order:
The lowest-ranked floating-point type, float , has a higher rank than any integer type.
Every complex floating-point type has the same rank as the type of its real and imaginary parts.
Integer Promotion
In any expression, you can always use a value whose type ranks lower than int in place of an operand of type int or unsigned int . You can also use a bit-field as an integer operand (bit-fields are discussed in Chapter 10 ). In these cases, the compiler applies integer promotion : any operand whose type ranks lower than int is automatically converted to the type int , provided int is capable of representing all values of the operand’s original type. If int is not sufficient, the operand is converted to unsigned int .
Integer promotion always preserves the value of the operand. Some examples:
In the last of these statements, the compiler promotes the first addend, the value of var , to the type int or unsigned int before performing the addition. If int and short have the same width, which is likely on a 16-bit computer, then the signed type int is not wide enough to represent all possible values of the unsigned short variable var . In this case, the value of var is promoted to unsigned int . After the addition, the result is converted to unsigned short for assignment to var .
Usual Arithmetic Conversions
The usual arithmetic conversions are the implicit conversions that are automatically applied to operands of different arithmetic types for most operators. The purpose of the usual arithmetic conversions is to find a common real type for all of the operands and the result of the operation.
The usual arithmetic conversions are performed implicitly for the following operators:
Arithmetic operators with two operands: * , / , % , + , and -
Relational and equality operators: < , <= , > , >= , == , and !=
The bitwise operators, & , | , and ^
The conditional operator, ?: (for the second and third operands)
With the exception of the relational and equality operators, the common real type obtained by the usual arithmetic conversions is generally the type of the result. However, if one or more of the operands has a complex floating-point type, then the result also has a complex floating-point type.
The usual arithmetic conversions are applied as follows:
If either operand has a floating-point type, then the operand with the lower conversion rank is converted to a type with the same rank as the other operand. Real types are converted only to real types, however, and complex types only to complex.
In other words, if either operand has a complex floating-point type, the usual arithmetic conversion matches only the real type on which the actual type of the operand is based. Some examples:
If both operands are integers, integer promotion is first performed on both operands. If after integer promotion the operands still have different types, conversion continues as follows:
If one operand has an unsigned type T whose conversion rank is at least as high as that of the other operand’s type, then the other operand is converted to type T .
Otherwise, one operand has a signed type T whose conversion rank is higher than that of the other operand’s type. The other operand is converted to type T only if type T is capable of representing all values of its previous type. If not, then both operands are converted to the unsigned type that corresponds to the signed type T .
The following lines of code contain some examples:
In this example, to evaluate the comparison in the if condition, the value of i , −1, must first be converted to the type unsigned int . The result is a large positive number. On a 32-bit system, that number is 2 32 − 1, and on any system it is greater than limit . Hence, the if condition is false.
In the last line of the example, the value of limit is converted to n ’s type, long , if the value range of long contains the whole value range of unsigned int . If not—for example, if both int and long are 32 bits wide—then both multiplicands are converted to unsigned long .
The usual arithmetic conversions preserve the operand’s value, except in the following cases:
When an integer of great magnitude is converted to a floating-point type, the target type’s precision may not be sufficient to represent the number exactly.
Negative values are outside the value range of unsigned types.
In these two cases, values that exceed the range or precision of the target type are converted as described under " The Results of Arithmetic Type Conversions ,” later in this chapter.
Other Implicit Type Conversions
The compiler also automatically converts arithmetic values in the following cases:
In assignments and initializations, the value of the right operand is always converted to the type of the left operand.
In function calls, the arguments are converted to the types of the corresponding parameters. If the parameters have not been declared, then the default argument promotions are applied: integer promotion is performed on integer arguments, and arguments of type float are promoted to double .
In return statements, the value of the return expression is converted to the function’s return type.
In a compound assignment, such as x += 2.5 , the values of both operands are first subject to the usual arithmetic conversions, then the result of the arithmetic operation is converted, as for a simple assignment, to the type of the left operand. Some examples:
The Results of Arithmetic Type Conversions
Because the different types have different purposes, representational characteristics, and limitations, converting a value from one type to another often involves the application of special rules to deal with such peculiarities. In general, the exact result of a type conversion depends primarily on the characteristics of the target type.
Conversions to _Bool
Any value of any scalar type can be converted to _Bool . The result is 0—i.e., false —if the scalar value is equal to 0; and 1, or true , if it is nonzero. Because a null pointer compares equal to zero, its value becomes false on conversion to _Bool .
Conversions to unsigned integer types other than _Bool
Integer values are always preserved if they are within the range of the new unsigned type—in other words, if they are between 0 and U type _MAX , where U type _MAX is the greatest value that can be represented by unsigned type .
For values outside the new unsigned type’s range, the value after conversion is the value obtained by adding or subtracting ( U type _MAX + 1) as many times as necessary until the result is within the range of the new type. The following example illustrates the assignment of a negative value to an unsigned integer type:
To adjust a signed value of −1 to the variable’s unsigned type, the program implicitly adds USHRT_MAX + 1 to it until a result within the type’s range is obtained. Because −1 + ( USHRT_MAX + 1) = USHRT_MAX , the final statement in the previous example is equivalent to n = USHRT_MAX; .
For positive integer values, subtracting ( U type _MAX + 1) as often as necessary to bring the value into the new type’s range is the same as the remainder of a division by ( U type _MAX + 1), as the following example illustrates:
If unsigned short is 16 bits wide, then its maximum value, USHRT_MAX , is hexadecimal FFFF. When the value FEDCBA is converted to unsigned short , the result is the same as the remainder of a division by hexadecimal 10000 (that’s USHRT_MAX + 1), which is always FFFF or less. In this case, the value assigned to n is hexadecimal DCBA.
To convert a real floating-point number to an unsigned or signed integer type, the compiler discards the fractional part. If the remaining integer portion is outside the range of the new type, the result of the conversion is undefined. Example:
In the initialization of n in this example, the value of x is converted from double to unsigned long by discarding its fractional part, 0.9. The integer part, 2, is the value assigned to n . In the initialization of m , the C99 function round() rounds the value of x to the nearest integer value (whether higher or lower), and returns a value of type double . The fractional part of the resulting double value—3.0 in this case—is thus equal to zero before being discarded through type conversion for the assignment to m .
When a complex number is converted to an unsigned integer type, the imaginary part is first discarded. Then the resulting floating-point value is converted as described previously. Example:
The imaginary part of z is discarded, leaving the real floating-point value −1.7. Then the fractional part of the floating-point number is also discarded. The remaining integer value, −1, is converted to unsigned int by adding UINT_MAX +1, so that the value ultimately assigned to n is equal to UINT_MAX .
Conversions to signed integer types
The problem of exceeding the target type’s value range can also occur when a value is converted from an integer type, whether signed or unsigned, to a different, signed integer type; for example, when a value is converted from the type long or unsigned int to the type int . The result of such an overflow on conversion to a signed integer type, unlike conversions to unsigned integer types, is left up to the implementation.
Most compilers discard the highest bits of the original value’s binary representation and interpret the lowest bits according to the new type. As the following example illustrates, under this conversion strategy the existing bit pattern of an unsigned int is interpreted as a signed int value:
However, depending on the compiler, such a conversion attempt may also result in a signal being raised to inform the program of the value range overflow.
When a real or complex floating-point number is converted to a signed integer type, the same rules apply as for conversion to an unsigned integer type, as described in the previous section.
Conversions to real floating-point types
Not all integer values can be exactly represented in floating-point types. For example, although the value range of the type float includes the range of the types long and long long , float is precise to only six decimal digits. Thus, some long values cannot be stored exactly in a float object. The result of such a conversion is the next lower or next higher representable value, as the following example illustrates:
Remember that the subtraction in this example, like all floating-point arithmetic, is performed with at least double precision (see " Floating-Point Types " in Chapter 2 ). Typical output produced by this code is:
Any value in a floating-point type can be represented exactly in another floating-point type of greater precision. Thus when a double value is converted to long double , or when a float value is converted to double or long double , the value is exactly preserved. In conversions from a more precise to a less precise type, however, the value being converted may be beyond the range of the new type. If the value exceeds the target type’s range, the result of the conversion is undefined. If the value is within the target type’s range, but not exactly representable in the target type’s precision, then the result is the next smaller or next greater representable value. The program in Example 2-2 illustrates the rounding error produced by such a conversion to a less-precise floating-point type.
When a complex number is converted to a real floating-point type, the imaginary part is simply discarded, and the result is the complex number’s real part, which may have to be further converted to the target type as described in this section.
Conversions to complex floating-point types
When an integer or a real floating-point number is converted to a complex type, the real part of the result is obtained by converting the value to the corresponding real floating-point type as described in the previous section. The imaginary part is zero.
When a complex number is converted to a different complex type, the real and imaginary parts are converted separately according to the rules for real floating-point types.
In the first of these two initializations, the integer constant 2 is implicitly converted to double _Complex for assignment to dz . The resulting value of dz is 2.0 + 0.0 × I .
In the initialization of fz , the two parts of the double _Complex value of dz are converted (after the addition) to float , so that the real part of fz is equal to 2.0F , and the imaginary part 1.0F .
Conversion of Nonarithmetic Types
Pointers and the names of arrays and functions are also subject to certain implicit and explicit type conversions. Structures and unions cannot be converted, although pointers to them can be converted to and from other pointer types.
Array and Function Designators
An array or function designator is any expression that has an array or function type. In most cases, the compiler implicitly converts an expression with an array type, such as the name of an array, into a pointer to the array’s first element. The array expression is not converted into a pointer only in the following cases:
When the array is the operand of the sizeof operator
When the array is the operand of the address operator &
When a string literal is used to initialize an array of char or wchar_t
The following examples demonstrate the implicit conversion of array designators into pointers, using the conversion specification %p to print pointer values:
In the initialization of array_length in this example, the expression sizeof(iArray) yields the size of the whole array, not the size of a pointer. However, the same identifier iArray is implicitly converted to a pointer in the other three statements in which it appears:
As an argument in the first printf() call.
As the operand of the dereferencing operator * .
In the pointer arithmetic operations and assignment to iPtr (see also " Modifying and Comparing Pointers " in Chapter 9 ).
The names of character arrays are used as pointers in string operations, as in this example:
In the function call strlen(msg) in this example, the array identifier msg is implicitly converted to a pointer to the array’s first element with the function parameter’s type, const char * . Internally, strlen() merely counts the characters beginning at that address until the first null character, the string terminator.
Similarly, any expression that designates a function, such as a function name, can also be implicitly converted into a pointer to the function. Again, this conversion does not apply when the expression is the operand of the address operator & . The sizeof operator cannot be used with an operand of function type. The following example illustrates the implicit conversion of function names to pointers. The program initializes an array of pointers to functions, then calls the functions in a loop.
Explicit Pointer Conversions
To convert a pointer from one pointer type to another, you must usually use an explicit cast. In some cases the compiler provides an implicit conversion: these cases are described in " Implicit Pointer Conversions ,” later in this chapter. Pointers can also be explicitly converted into integers, and vice versa.
Object pointers
You can explicitly convert an object pointer—that is, a pointer to a complete or incomplete object type—to any other object pointer type. In your program, you must ensure that your use of the converted pointer makes sense. An example:
If the object pointer after conversion does not have the alignment required by the new type, the results of using the pointer are undefined. In all other cases, converting the pointer value back into the original pointer type is guaranteed to yield an equivalent to the original pointer.
If you convert any type of object pointer into a pointer to any char type ( char , signed char , or unsigned char ), the result is a pointer to the first byte of the object. The first byte is considered here to be the byte with the lowest address, regardless of the system’s byte order structure. The following example uses this feature to print a hexadecimal dump of a structure variable:
This example produces output like the following:
The output of the first two bytes, 23 01 , shows that the code was executed on a little-endian system: the byte with the lowest address in the structure myData was the least significant byte of the short member id .
Function pointers
The type of a function always includes its return type, and may also include its parameter types. You can explicitly convert a pointer to a given function into a pointer to a function of a different type. In the following example, the typedef statement defines a name for the type “function that has one double parameter and returns a double value”:
In this example, the function pointer pFunc is assigned the addresses of functions that have different types. However, if the program uses the pointer to call a function whose definition does not match the exact function pointer type, the program’s behavior is undefined.
Implicit Pointer Conversions
The compiler converts certain types of pointers implicitly. Assignments, conditional expressions using the equality operators == and != , and function calls involve implicit pointer conversion in three kinds of cases, which are described individually in the sections that follow. The three kinds of implicit pointer conversion are:
Any object pointer type can be implicitly converted to a pointer to void , and vice versa.
Any pointer to a given type can be implicitly converted into a pointer to a more qualified version of that type—that is, a type with one or more additional type qualifiers.
A null pointer constant can be implicitly converted into any pointer type.
Pointers to void
Pointers to void —that is, pointers of the type void * —are used as “multipurpose” pointers to represent the address of any object, without regard for its type. For example, the malloc() function returns a pointer to void (see Example 2-3 ). Before you can access the memory block, the void pointer must always be converted into a pointer to an object.
Example 4-1 demonstrates more uses of pointers to void . The program sorts an array using the standard function qsort() , which is declared in the header file stdlib.h with the following prototype:
The qsort() function sorts the array in ascending order, beginning at the address array , using the quick-sort algorithm. The array is assumed to have n elements whose size is element_size .
The fourth parameter, compare , is a pointer to a function that qsort() calls to compare any two array elements. The addresses of the two elements to be compared are passed to this function in its pointer parameters. Usually this comparison function must be defined by the programmer. It must return a value that is less than, equal to, or greater than 0 to indicate whether the first element is less than, equal to, or greater than the second.
Example 4-1. A comparison function for qsort()
In Example 4-1 , the malloc() function returns a void * , which is implicitly converted to float * in the assignment to pNumbers . In the call to qsort() , the first argument pNumbers is implicitly converted from float * to void * , and the function name floatcmp is implicitly interpreted as a function pointer. Finally, when the floatcmp() function is called by qsort() , it receives arguments of the type void * , the “universal” pointer type, and must convert them explicitly to float * before dereferencing them to initialize its float variables.
Pointers to qualified object types
The type qualifiers in C are const , volatile , and restrict (see Chapter 11 for details on these qualifiers). For example, the compiler implicitly converts any pointer to int into a pointer to const int where necessary. If you want to remove a qualification rather than adding one, however, you must use an explicit type conversion, as the following example illustrates:
The second to last statement in this example illustrates why pointers to const -qualified types are sometimes called read-only pointers : although you can modify the pointers’ values, you can’t use them to modify objects they point to.
Null pointer constants
A null pointer constant is an integer constant with the value 0, or a constant integer value of 0 cast as a pointer to void . The macro NULL is defined in the header files stdlib.h , stdio.h , and others as a null pointer constant. The following example illustrates the use of the macro NULL as a pointer constant to initialize pointers rather than an integer zero or a null character:
When you convert a null pointer constant to another pointer type, the result is called a null pointer . The bit pattern of a null pointer is not necessarily zero. However, when you compare a null pointer to zero, to NULL , or to another null pointer, the result is always true . Conversely, comparing a null pointer to any valid pointer to an object or function always yields false .
Conversions Between Pointer and Integer Types
You can explicitly convert a pointer to an integer type, and vice versa. The result of such conversions depends on the compiler, and should be consistent with the addressing structure of the system on which the compiled executable runs. Conversions between pointer and integer types can be useful in system programming, and necessary when programs need to access specific physical addresses, such as ROM or memory-mapped I/O registers.
When you convert a pointer to an integer type whose range is not large enough to represent the pointer’s value, the result is undefined. Conversely, converting an integer into a pointer type does not necessarily yield a valid pointer. A few examples:
The last three statements obtain information about the hardware configuration from the system data table, assuming the operating environment allows the program to access that memory area. In a DOS program compiled with the large memory model, pointers are 32 bits wide and consist of a segment address in the higher 16 bits and an offset in the lower 16 bits (often written in the form segment : offset ). Thus the pointer biosPtr in the prior example can be initialized with a long integer constant.
Get C in a Nutshell now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.
Don’t leave empty-handed
Get Mark Richards’s Software Architecture Patterns ebook to better understand how to design components—and how they should interact.
It’s yours, free.

Check it out now on O’Reilly
Dive in for free with a 10-day trial of the O’Reilly learning platform—then explore all the other resources our members count on to build skills and solve problems every day.

- Coding Ground
- Corporate Training

- C Programming Tutorial
- C - Overview
- C - Environment Setup
- C - Program Structure
- C - Basic Syntax
- C - Data Types
- C - Variables
- C - Constants
- C - Storage Classes
- C - Operators
- C - Decision Making
- C - Functions
- C - Scope Rules
- C - Pointers
- C - Strings
- C - Structures
- C - Bit Fields
- C - Typedef
- C - Input & Output
- C - File I/O
- C - Preprocessors
- C - Header Files
C - Type Casting
- C - Error Handling
- C - Recursion
- C - Variable Arguments
- C - Memory Management
- C - Command Line Arguments
- C Programming useful Resources
- C - Questions & Answers
- C - Quick Guide
- C - Useful Resources
- C - Discussion
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
Converting one datatype into another is known as type casting or, type-conversion. For example, if you want to store a 'long' value into a simple integer then you can type cast 'long' to 'int'. You can convert the values from one type to another explicitly using the cast operator as follows −
Consider the following example where the cast operator causes the division of one integer variable by another to be performed as a floating-point operation −
When the above code is compiled and executed, it produces the following result −
It should be noted here that the cast operator has precedence over division, so the value of sum is first converted to type double and finally it gets divided by count yielding a double value.
Type conversions can be implicit which is performed by the compiler automatically, or it can be specified explicitly through the use of the cast operator . It is considered good programming practice to use the cast operator whenever type conversions are necessary.
Integer Promotion
Integer promotion is the process by which values of integer type "smaller" than int or unsigned int are converted either to int or unsigned int . Consider an example of adding a character with an integer −
Here, the value of sum is 116 because the compiler is doing integer promotion and converting the value of 'c' to ASCII before performing the actual addition operation.
Usual Arithmetic Conversion
The usual arithmetic conversions are implicitly performed to cast their values to a common type. The compiler first performs integer promotion ; if the operands still have different types, then they are converted to the type that appears highest in the following hierarchy −

The usual arithmetic conversions are not performed for the assignment operators, nor for the logical operators && and ||. Let us take the following example to understand the concept −
Here, it is simple to understand that first c gets converted to integer, but as the final value is double, usual arithmetic conversion applies and the compiler converts i and c into 'float' and adds them yielding a 'float' result.
ConvertDataTypes .com Convert data types programming in one click !
Convert unsigned int to int in objective c.
- unsigned int vIn = 0;
- int vOut = (int)vIn;
The most viewed convertions in Objective C
- Convert long to int in C 103932 hits
- Convert int to long in C 78325 hits
- Convert unsigned char to int in C 74481 hits
- Convert char* to int in C 63331 hits
- Convert long to double in C 43856 hits
- Convert unsigned long to int in C 41730 hits
- Convert float to double in C 41571 hits
- Convert short to int in C 40121 hits
- Convert long to float in C 38911 hits
- Convert float to unsigned int in C 38395 hits
- Convert int to bool in C 36151 hits
- Convert long to char* in C 35065 hits
- Convert char* to wchar_t* in C 34642 hits
- Convert int to wchar_t in C 33980 hits
- Convert bool to char* in C 33494 hits
- Convert unsigned char to float in C 32671 hits
- Convert char* to unsigned char in C 31678 hits
- Convert double to unsigned long in C 30533 hits
- Convert unsigned short to float in C 28692 hits
- Convert double to unsigned char in C 28478 hits

IMAGES
VIDEO
COMMENTS
Hepatitis C, a virus that attacks the liver, is a tricky disease. Some people have it and may never know it as they are affected by any sorts of symptoms. It can remain silent until there is severe damage to your liver.
Whether in the form of a fizzy drink or flavored lozenges, cold and flu preventative supplements almost always highlight vitamin C as one of their key ingredients. So, what’s so magical about vitamin C? Also known as ascorbic acid, vitamin ...
Hansen Communication Lab developed the concept of the five C’s of communication, which are the following: articulate clearly; speak correctly; be considerate; give compliments; and have confidence.
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 x; unsigned int y = ( unsigned int )x;. Of course if it's a negative number you will end up with some strange results. Last edited on Nov
In C++ there are two types of integer variables known as signed and unsigned. As briefly mentioned, when you convert large, unsigned integers to
When the compiler converts an unsigned integer to a floating-point type, if the original value isn't representable exactly in the result type
int a = 6; unsigned int b; int c; b = (unsigned int)a; c = (int)b;. Actually in many cases you can dispense with the cast. However many
To convert a real floating-point number to an unsigned or signed integer type, the compiler discards the fractional part. If the remaining integer portion is
unsigned short x = 45000, y = 50000; unsigned int z = x * (unsigned int)y;. e C integer conversion rules define how C compilers handle conversions. These rules
For example, if you want to store a 'long' value into a simple integer then you can type cast 'long' to 'int'. You can convert the values from one type to
Convert unsigned int to int in Objective C · unsigned int vIn = 0; · int vOut = (int)vIn;
1) Add UINT_MAX + 1 to your signed number and store it in an unsigned variable. (this will convert the signed integer to an unsigned integer of same magnitude).
Unsigned int is a data type that can store the data values from zero to positive numbers whereas signed int can store negative values also. It is usually more