← Back to AILP Home

Unsigned Integers — uint

Widths: uint1, uint2, uint4, uint8, uint16, uint32, uint64, uint128, uint256, uint512, uint1024, uint2048, uint4096

Overview

Unsigned integers store non-negative values only. Required for bitwise operations (&, |, ^, ~, <<, >>).

Width Table

Type Bytes Range Alias Notes
uint1 1 0 to 1 u1 Single bit
uint2 1 0 to 3 u2
uint4 1 0 to 15 u4
uint8 1 0 to 255 u8 Byte
uint16 2 0 to 65535 u16
uint32 4 0 to 2^32-1 u32
uint64 8 0 to 2^64-1 u64
uint128 16 0 to 2^128-1 u128 LBIM
uint256 32 0 to 2^256-1 u256 LBIM
uint512 64 0 to 2^512-1 u512 LBIM
uint1024 128 0 to 2^1024-1 u1024 LBIM
uint2048 256 0 to 2^2048-1 u2048 LBIM
uint4096 512 0 to 2^4096-1 u4096 LBIM

Declaration

uint32:flags = 0xFF00u32;
uint64:addr = 0xDEADBEEFu64;
uint8:byte = 255u8;

Literal Suffixes

Every supported unsigned integer width has a corresponding literal suffix: u1, u2, u4, u8, u16, u32, u64, u128, u256, u512, u1024, u2048, u4096.

Nitpick supports hexadecimal and binary literal formats:

uint8:hex   = 0xFFu8;
uint32:hex  = 0xDEADBEEFu32;
uint64:zero = 0x0u64;
uint8:bin   = 0b11111111u8;

[!WARNING] Nitpick rejects negative literals for uint types. For example, -1u8 is a compile error. If you need two's complement reinterpretation, you must use an explicit cast from a signed integer (e.g., @cast<uint32>(-1i32)).

Overflow Behavior

Unsigned arithmetic wraps silently (modular arithmetic). When a computation exceeds the maximum value for the type, it wraps around to zero. When it goes below zero, it wraps around to the maximum value.

uint8:max = 255u8;
uint8:wrapped = max + 1u8; // wrapped == 0u8

uint8:min = 0u8;
uint8:underflow = min - 1u8; // underflow == 255u8

[!NOTE] This differs from TBB (tbb) types, which trap to an ERR sentinel value on overflow. Checked overflow functions for unsigned integers are planned for a future release (0.55 math series).

Bitwise Operations

Bitwise ops require unsigned types:

uint32:a = 0xFF00u32;
uint32:b = 0x0FF0u32;
uint32:and_result = (a & b);   // 0x0F00
uint32:or_result  = (a | b);   // 0xFFF0
uint32:xor_result = (a ^ b);   // 0xF0F0
uint32:not_result = (~a);      // 0xFFFF00FF
uint32:shl = (a << 4u32);     // 0xF0000
uint32:shr = (a >> 4u32);     // 0x0FF0

uint1 vs bool

uint1 and bool both map to LLVM's i1 type under the hood, but they are semantically distinct types in the Nitpick type system.

They cannot be implicitly converted. You must use an explicit cast:

bool:b = true;
uint1:u = @cast<uint1>(b); // Valid: u == 1u1

Arithmetic on uint1 follows modulo-2 wrapping: 1u1 + 1u1 == 0u1.

C FFI Mapping

When interacting with C code via extern blocks, Nitpick unsigned integers map to standard C types as follows:

Nitpick C Type Size
uint8 unsigned char 1 byte
uint16 unsigned short 2 bytes
uint32 unsigned int 4 bytes
uint64 unsigned long long 8 bytes

[!NOTE] Standard C does not have a cross-platform equivalent for uint128 or larger types. When interfacing with GCC/Clang, you can use __uint128_t for uint128. For larger LBIM types (uint256+), they must be passed as pointers to structs at the C ABI level.

LBIM Types (≥128 bit)

Same limb-based model as signed integers. See int.md for LBIM details. Passed via sret/byval at ABI level.

Related