uint8: the 8-bit unsigned integer
uint8 holds every whole number from 0 to 255, which is 0 to 2⁸ − 1. That is 2⁸ = 256 values in 8 bits, none of them negative.
uint8 limits
- Maximum
- 255power2⁸ − 1hex0xFFbinary1111 1111
- Minimum
- 0power0hex0x00binary0000 0000
- Distinct values
- 2⁸ = 256
- Size
- 8 bits, 1 byte
uint8 overflow playground
Starts at the maximum, one step from overflowing. Change the operation, the value or the type, or cast to another width, and watch the bits wrap.
Decimal, 0x hex or 0b binary, with a minus sign if negative. 2^31 − 1 works too.
Struck-through bits are dropped.
- Exact answer: 256.
- That is above the maximum of uint8, 255.
- The hardware keeps only the low 8 bits, which is the same as taking the answer modulo 2⁸ = 256: 0.
What uint8 is called in each language
| Language | Type | Limits in code | Note |
|---|---|---|---|
| C and C++ | uint8_t | UINT8_MAX | |
| Java | none | byte is signed; Byte.toUnsignedInt(b) reads one as 0 to 255. | |
| C# | byte | byte.MaxValue | |
| Rust | u8 | u8::MAX | |
| Go | uint8 (alias byte) | math.MaxUint8 | |
| Swift | UInt8 | UInt8.max | |
| Kotlin | UByte | UByte.MAX_VALUE | |
| MySQL | TINYINT UNSIGNED | ||
| PostgreSQL | none | PostgreSQL has no unsigned integer types. | |
| SQL Server | tinyint | The only unsigned integer type in SQL Server. | |
| JavaScript | Uint8Array element | Uint8ClampedArray clamps to 0 and 255 instead of wrapping. | |
| Python | ctypes.c_uint8 | Each item of a bytes object is 0 to 255. |
Only names with exactly 8 bits on every platform are listed as the type.
What happens when uint8 overflows
In 8 bits, 255 + 1 wraps to 0, and 0 − 1 wraps to 255. The processor keeps the low 8 bits of the answer, which is the same as working modulo 2⁸. You can see it in JavaScript:
new Uint8Array([255 + 1])[0] → 0
Whether a program is allowed to wrap like that depends on the language:
| Language | By default | To check or wrap on purpose |
|---|---|---|
| C and C++ | Unsigned types wrap around modulo 2ⁿ. Signed overflow is undefined behaviour: the compiler may assume it never happens and optimise on that basis. Types narrower than int are promoted to int first, so even uint16_t × uint16_t can overflow a signed int. | __builtin_add_overflow (GCC, Clang); ckd_add in C23’s <stdckdint.h>; -fsanitize=undefined to catch it |
| Java | Wraps around silently, in two’s complement. | Math.addExact, multiplyExact and friends throw ArithmeticException |
| C# | Wraps around, unless the code is in a checked context, which throws OverflowException. A constant expression that overflows is a compile error. | checked(...) blocks, or the CheckForOverflowUnderflow compiler option |
| Rust | Panics in debug builds. Release builds wrap, unless overflow-checks is turned on for that profile. | checked_add, wrapping_add, saturating_add, overflowing_add |
| Go | Wraps around silently. Only constant expressions that overflow are compile errors. | math/bits.Add64 reports the carry; Mul64 returns the high half of the product |
| Swift | Traps: the program stops with a runtime error. | &+, &-, &* wrap on purpose; addingReportingOverflow reports it |
| Kotlin | Wraps around silently, like Java. | Math.addExact on the JVM |
| JavaScript | Numbers never wrap, but lose precision past 2⁵³. Bitwise operators and typed arrays wrap to their width. BigInt never overflows. | Number.isSafeInteger; BigInt.asIntN and asUintN to wrap deliberately |
| Python | int never overflows: it grows as needed. | ctypes and NumPy fixed-width types do wrap |
| SQL | An error: the statement fails with an out of range or arithmetic overflow message. | MySQL outside strict mode clips an out-of-range value stored into a column to the limit, with a warning |
In C and C++, arithmetic on 8-bit types is done in int, so the sum itself does not overflow; it wraps when stored back into the uint8_t. For unsigned types that conversion is always defined: it wraps.
Common mistakes with uint8
- Counting down to zero with an unsigned counter. A loop such as for (i = n; i >= 0; i--) never ends when i is uint8: i >= 0 is always true, and 0 − 1 wraps to 255. Test i > 0 and use i − 1 inside, or use a signed counter.
- Expecting a byte sum in C to wrap straight away. Two uint8_t values are promoted to int before they are added, so 200 + 100 is 300 until it is stored back into a uint8_t, where it becomes 44. Comparing the sum with 255 before storing it therefore works.
When uint8 overflowed for real
Pac-Man level 256
The arcade Pac-Man keeps its level number in a single byte. On level 256 the routine that draws the bonus fruit at the bottom of the screen goes wrong when that count overflows: it draws far more than it should, garbles the right half of the maze and leaves a level that cannot be finished.
Where you meet uint8
- One byte of memory or a file
- Each red, green or blue channel of a 24-bit colour
- Each part of an IPv4 address
Need negative numbers? The signed type of the same width is int8, from −128 to 127.
Every integer type
| Type | Minimum | Maximum |
|---|---|---|
| int8 | −128 | 127 |
| uint8 this page | 0 | 255 |
| int16 | −32, |
32, |
| uint16 | 0 | 65, |
| int32 | −2, |
2, |
| uint32 | 0 | 4, |
| int64 | −9, |
9, |
| uint64 | 0 | 18, |
| int128 | −170, |
170, |
| uint128 | 0 | 340, |
Questions
What is the maximum value of uint8?
255, which is 2⁸ − 1 or 0xFF in hex. The minimum is 0.
Why does uint8 start at 0?
An unsigned type spends all 8 bits on magnitude and none on a sign, so it cannot hold negative numbers but reaches twice as far: 255 instead of the 127 of int8. Subtracting 1 from 0 wraps to the maximum.
How many values can uint8 hold?
2⁸ = 256 distinct values, from 0 to 255.
What happens when uint8 overflows?
On the hardware the result keeps only its low 8 bits, so 255 + 1 becomes 0. In C, C++, C# and Kotlin, arithmetic on 8-bit values is done in int (UInt in Kotlin), so 255 + 1 is 256 as an int; it becomes 0 only when stored back into the 8-bit type, as x++, a cast or (except in Kotlin, where it does not compile) x += 1 do. Go wraps at 8 bits directly, Rust panics in debug builds and wraps in release builds, and Swift stops with a runtime error.
What is uint8 called in other languages?
C and C++: uint8_t; C#: byte; Rust: u8; Go: uint8 (alias byte); Swift: UInt8; Kotlin: UByte; Python: ctypes.c_uint8. In SQL: TINYINT UNSIGNED in MySQL, tinyint in SQL Server.