int8: the 8-bit signed integer
int8 holds every whole number from −128 to 127, which is −2⁷ to 2⁷ − 1. That is 2⁸ = 256 values in 8 bits, stored in two’s complement.
int8 limits
- Maximum
- 127power2⁷ − 1hex0x7Fbinary0111 1111
- Minimum
- −128power−2⁷hex0x80binary1000 0000
- Distinct values
- 2⁸ = 256
- Size
- 8 bits, 1 byte
The hex and binary forms are the bit patterns. The top bit is the sign: 0 for the maximum, 1 for the minimum.
int8 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.
The solid underlined bit is the sign bit: 1 means negative in a signed type. Struck-through bits are dropped.
- Exact answer: 128.
- That is above the maximum of int8, 127.
- The hardware keeps only the low 8 bits, which is the same as taking the answer modulo 2⁸ = 256: 128.
- The top bit is 1, so read as signed it is 128 − 256 = −128.
What int8 is called in each language
| Language | Type | Limits in code | Note |
|---|---|---|---|
| C and C++ | int8_t | INT8_MIN, INT8_MAX | Plain char may be signed or unsigned, depending on the platform. |
| Java | byte | Byte.MIN_VALUE, Byte.MAX_VALUE | |
| C# | sbyte | sbyte.MinValue, sbyte.MaxValue | |
| Rust | i8 | i8::MIN, i8::MAX | |
| Go | int8 | math.MinInt8, math.MaxInt8 | |
| Swift | Int8 | Int8.min, Int8.max | |
| Kotlin | Byte | Byte.MIN_VALUE, Byte.MAX_VALUE | |
| MySQL | TINYINT | ||
| PostgreSQL | none | The smallest integer type is smallint, 16 bits. | |
| SQL Server | none | tinyint is unsigned: 0 to 255, not −128 to 127. | |
| JavaScript | Int8Array element | There is no 8-bit scalar; numbers are 64-bit floats. | |
| Python | ctypes.c_int8 | Python’s own int has no fixed width and never overflows. |
Only names with exactly 8 bits on every platform are listed as the type.
What happens when int8 overflows
In 8 bits, 127 + 1 wraps to −128, and −128 − 1 wraps to 127. The processor keeps the low 8 bits of the answer, which is the same as working modulo 2⁸, and the top bit then decides the sign. You can see it in JavaScript:
new Int8Array([127 + 1])[0] → -128
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 int8_t. That conversion is implementation defined in C (GCC and Clang wrap) and defined as wrapping since C++20.
Common mistakes with int8
- Negating −128 or taking its absolute value. The exact answer, 128, is one past the maximum of 127, so once it is stored as int8 it wraps back to −128: −x and abs(x) of the minimum stay negative.
- Reading Java bytes as 0 to 255. Java’s byte is signed, so a byte holding 0xFF reads as −1. Use b & 0xFF or Byte.toUnsignedInt(b) to get 255.
Where you meet int8
- Small signed offsets and deltas
- Java’s byte, which is signed, so a byte read as 0xFF is −1
Need no negatives and twice the reach? The unsigned type of the same width is uint8, from 0 to 255.
Every integer type
| Type | Minimum | Maximum |
|---|---|---|
| int8 this page | −128 | 127 |
| uint8 | 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 int8?
127, which is 2⁷ − 1 or 0x7F in hex. The minimum is −128 (−2⁷).
Why is the minimum of int8 one further from zero than the maximum?
8 bits make 2⁸ patterns. Two’s complement gives the half with the top bit set to the negatives, −128 to −1, and the other half to zero and the positives, 0 to 127. Zero takes one of the non-negative patterns, so there is one more negative number than positive. That is also why negating −128 overflows back to itself.
How many values can int8 hold?
2⁸ = 256 distinct values, from −128 to 127.
What happens when int8 overflows?
On the hardware the result keeps only its low 8 bits, so 127 + 1 becomes −128. In C, C++, Java, C# and Kotlin, arithmetic on 8-bit values is done in int, so 127 + 1 is 128 as an int; it becomes −128 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 int8 called in other languages?
C and C++: int8_t; Java: byte; C#: sbyte; Rust: i8; Go: int8; Swift: Int8; Kotlin: Byte; Python: ctypes.c_int8. In SQL: TINYINT in MySQL.