Ready to practice?
Sign up to access interactive coding exercises and track your progress.
Unsigned Integers
Understand unsigned integers and why signed types are usually preferred.
What are unsigned integers?
While signed integers can represent both positive and negative whole numbers, unsigned integers can only hold non-negative whole numbers (zero and positive integers).
Declaring unsigned integers
To create an unsigned integer, use the unsigned keyword before the type name:
unsigned short us{};
unsigned int ui{};
unsigned long ul{};
unsigned long long ull{};
Range of unsigned integers
A 1-byte unsigned integer has a range of 0 to 255. Compare this with a 1-byte signed integer's range of -128 to 127. Both store 256 unique values, but unsigned integers can represent positive values twice as large.
| Size | Range |
|---|---|
| 8-bit unsigned | 0 to 255 |
| 16-bit unsigned | 0 to 65,535 |
| 32-bit unsigned | 0 to 4,294,967,295 |
| 64-bit unsigned | 0 to 18,446,744,073,709,551,615 |
An n-bit unsigned integer has a range of 0 to (2^n)-1.
Unsigned integer overflow (wrap-around)
When an unsigned value exceeds its range, the behavior is well-defined: values "wrap around" (called modulo wrapping).
For example, in a 1-byte unsigned integer:
- 255 is the maximum value
- 256 wraps to 0
- 257 wraps to 1
Wrapping works in reverse too:
- 0 is the minimum value
- -1 wraps to 255
- -2 wraps to 254
#include <iostream>
int main()
{
unsigned short maximum{65535}; // largest 16-bit unsigned value
std::cout << "maximum was: " << maximum << '\n';
maximum = 65536; // exceeds range, wraps to 0
std::cout << "maximum is now: " << maximum << '\n';
return 0;
}
Why avoid unsigned integers?
Many developers recommend avoiding unsigned integers in most situations due to two problematic behaviors.
Problem 1: Easy to underflow
With unsigned integers, the lower bound is zero - close to where most values reside, making underflow easy:
#include <iostream>
int main()
{
unsigned int first{2};
unsigned int second{3};
std::cout << first - second << '\n'; // prints 4294967295 (wrong!)
return 0;
}
Mathematically, 2 - 3 equals -1, but unsigned integers can't represent -1. The result wraps to 4294967295.
Problem 2: Mixing signed and unsigned integers
When an operation involves one signed and one unsigned integer, the signed value converts to unsigned:
#include <iostream>
int main()
{
signed int negative{-1};
unsigned int positive{1};
if (negative < positive)
std::cout << "-1 is less than 1\n";
else
std::cout << "1 is less than -1\n"; // this executes!
return 0;
}
The -1 converts to 4294967295, so the comparison 4294967295 < 1 is false!
Prefer signed integers over unsigned integers for quantities (even non-negative ones) and mathematical operations. Avoid mixing signed and unsigned integers.
When to use unsigned integers
Despite the above, unsigned integers have legitimate uses:
- Bit manipulation operations
- When you need well-defined wrap-around behavior (encryption, random number generation)
- Array indexing (sometimes unavoidable)
- Embedded systems or memory-constrained environments
Unsigned Integers - Quiz
Test your understanding of the lesson.
Practice Exercises
Unsigned Integer Pitfalls
Explore the dangers of unsigned integers by observing wrap-around behavior when values go below zero.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!