R
RUSTY YELLOW PAGES

Hexadecimal integer literalLiteral


Explanation

A base-16 integer literal, prefixed with 0x, as in 0xFF_u8 or 0x1a2b3c.

Digits af may be upper- or lower-case, and can be mixed within the same literal (though consistent casing is the usual style convention). Underscores are allowed between digits, including immediately after the 0x prefix. Like all integer literals, an optional type suffix (0xffu8) can pin the type directly.

Usage examples

Declaring a memory address

let addr = 0x2000; // <- `0x` prefix marks a base-16 (hexadecimal) integer literal

Restriction: only the hex digits 09 and af/AF may appear after the 0x prefix (underscores and a type suffix like 0xFF_u8 are still allowed).

Bit manipulation and flags

Hex groups bits into 4-bit nibbles, so a multi-bit register mask reads as "which nibble, which bits" at a glance — far harder to see in decimal.

const TX_ENABLE: u32   = 0x0000_0001;
const RX_ENABLE: u32   = 0x0000_0002;
const PARITY_EVEN: u32 = 0x0000_0004;
const BAUD_MASK: u32   = 0x0000_0F00; // <- hex literal: a multi-bit mask, nibble boundaries stay visible

fn configure(control: u32) -> u32 {
    control | TX_ENABLE | RX_ENABLE | PARITY_EVEN
}

let baud_bits = configure(0) & BAUD_MASK;

Hex digits map exactly onto 4-bit groups, so a mask like 0x0F00 communicates "bits 8–11" directly — the readability reason register-level code conventionally writes masks in hex rather than decimal.

Numeric computation

Power-of-two sizes and addresses read as recognizable patterns in hex in a way their decimal equivalents don't, which matters for anything doing alignment arithmetic.

const PAGE_SIZE: usize = 0x1000; // <- hex literal: a power-of-two boundary reads clearly in hex

fn is_page_aligned(addr: usize) -> bool {
    addr & (PAGE_SIZE - 1) == 0
}

assert!(is_page_aligned(0x4000));
assert!(!is_page_aligned(0x4010));

0x1000 and 0x4000 are instantly recognizable as round, aligned values in a way 4096 and 16384 aren't — which is why systems code conventionally writes addresses and alignment constants in hex.

Explanation

Embedded support: Full

A hex literal means exactly the same thing under #![no_std] — pure lexical grammar, resolved at compile time. This is the single most embedded-relevant literal form in the whole set: peripheral register addresses and multi-bit masks are overwhelmingly written in hex in real firmware, because a microcontroller's reference manual lists every memory-mapped address and reset value in hex, and two hex digits map exactly onto one byte — so an 8-digit hex literal like 0x4001_0800 reads directly as "this 32-bit register, these four bytes," a correspondence decimal doesn't offer and binary only offers up to about a byte before it becomes too long to scan. Device crates generated by tools like svd2rust from a chip's SVD file, and essentially every HAL and peripheral-access crate, express addresses and reset/mask values in hex for exactly this reason.

Usage examples

Declaring a peripheral's base address from a reference manual

const GPIOA_BASE: u32 = 0x4001_0800; // <- hex literal: matches the address exactly as printed in the MCU reference manual

Deriving a register's address from a base and an offset

const RCC_BASE: u32           = 0x4002_1000;
const RCC_AHB1ENR_OFFSET: u32 = 0x30;
const RCC_AHB1ENR: u32 = RCC_BASE + RCC_AHB1ENR_OFFSET; // <- hex literals: base + offset, exactly as the reference manual documents it