Academy
Fundamental Types, Booleans, and Characters: The Building Blocks That Hardware Understands
Rust replaces C++'s ambiguous types with fixed-size primitives like `i32`, 4-byte Unicode `char`, and non-integer `bool` to deliver platform-independent safety.
7 menit baca
Di halaman ini
Every programming language sits on a foundation of primitive types—the atoms from which all data structures are built. Numbers, characters, booleans, arrays. These aren't glamorous. Nobody writes blog posts about bool. Nobody gives conference talks titled "The Fascinating World of i32." And yet, these types are where your program meets the hardware, where your abstractions become actual bits in actual memory, and where subtle misunderstandings cause bugs that are extraordinarily difficult to diagnose.
C++ has a notoriously complex primitive type system. char might be signed or unsigned depending on the platform. int is "at least 16 bits" but could be 32 or 64. long is "at least as big as int" but exactly how much bigger is anyone's guess. bool can be implicitly converted to int, leading to code where true + true == 2 is a valid expression. The result is a type system where portability requires constant vigilance and defensive coding.
Rust looked at this situation and chose clarity over compatibility. Every primitive type has a fixed, known size. i32 is always 32 bits—not "at least 32 bits" or "typically 32 bits on most platforms." char is always a 4-byte Unicode scalar value—not "an 8-bit value that might be signed or unsigned depending on your compiler settings." bool is true or false—not an integer that happens to be zero or nonzero.
At RantAI, this clarity saves us time every day. We don't need to check whether our assumptions about type sizes are valid on the deployment platform. We don't debug subtle sign-extension bugs caused by ambiguous char signedness. We just use the types, and they work as documented, everywhere. This article, drawn from Chapter 8, Sections 8.2.1 through 8.2.3 of our guide "The Rust Programming Language," covers the fundamental types that form the foundation of every Rust program.
The Type System Overview#
Rust's fundamental types fall into clear categories:
// Boolean — exactly two values
let flag: bool = true;
// Character — 4-byte Unicode scalar value
let letter: char = 'A';
let emoji: char = '🦀';
let kanji: char = '漢';
// Integers — signed and unsigned, fixed sizes
let small: i8 = -128; // 8-bit signed: -128 to 127
let byte: u8 = 255; // 8-bit unsigned: 0 to 255
let default_int: i32 = 42; // 32-bit signed (the default integer type)
let big: i64 = 9_000_000_000; // 64-bit signed
let huge: i128 = 170_141_183_460_469_231_731_687_303_715_884_105_727; // 128-bit!
let size: usize = 1024; // Pointer-sized unsigned (for indexing)
// Floating-point — IEEE 754
let single: f32 = 3.14; // 32-bit (7 decimal digits of precision)
let double: f64 = 3.141592653589793; // 64-bit (15 decimal digits, the default)
// Unit type — absence of value
let nothing: () = (); // Rust's replacement for void
Notice something important: every type has a specific, documented, platform-independent size. i32 is 32 bits on x86, on ARM, on RISC-V, on WebAssembly. There's no "well, it depends on the implementation" hedging. This is a deliberate design choice that makes Rust code portable by default.
Booleans: Two Values, No Surprises#
fn main() {
let is_valid: bool = true;
let is_empty: bool = false;
// Boolean operations
let both = is_valid && !is_empty; // logical AND with NOT
let either = is_valid || is_empty; // logical OR
// Comparisons produce booleans
let x = 42;
let is_positive: bool = x > 0;
let is_answer: bool = x == 42;
// Booleans are NOT integers — no implicit conversion!
// let sum = true + true; // COMPILE ERROR: can't add booleans
// if 1 { ... } // COMPILE ERROR: condition must be bool
// Explicit conversion when you genuinely need it
let one: i32 = true as i32; // 1
let zero: i32 = false as i32; // 0
}
The critical difference from C/C++: in Rust, bool is not secretly an integer. You can't write if 1 { ... } because 1 is not a bool. You can't write true + true because addition isn't defined for booleans. This might seem restrictive, but it eliminates an entire category of bugs where integers are accidentally used as boolean conditions (or vice versa). Every if condition must be explicitly bool. No ambiguity. No "is zero false or is false zero?" confusion.
Characters: Unicode from Day One#
fn main() {
// char is a 4-byte Unicode scalar value
let ascii: char = 'A'; // U+0041
let accented: char = 'é'; // U+00E9
let cjk: char = '漢'; // U+6F22
let emoji: char = '🦀'; // U+1F980
let math: char = '∑'; // U+2211
// Size is always 4 bytes
assert_eq!(std::mem::size_of::<char>(), 4);
// Characters have numeric values (Unicode code points)
println!("'A' = U+{:04X}", 'A' as u32); // U+0041
println!("'🦀' = U+{:04X}", '🦀' as u32); // U+1F980
// Character classification
println!("Is alphabetic: {}", 'A'.is_alphabetic()); // true
println!("Is digit: {}", '7'.is_ascii_digit()); // true
println!("Is uppercase: {}", 'A'.is_uppercase()); // true
println!("Lowercase: {}", 'A'.to_lowercase()); // a
// u8 for ASCII-specific work
let ascii_byte: u8 = b'A'; // 65 — single byte, ASCII only
}
Rust's char is 4 bytes because Unicode requires it. A Unicode scalar value can be up to U+10FFFF, which doesn't fit in 1 or 2 bytes. By making char always 4 bytes, Rust ensures that every char can hold any Unicode character without encoding tricks or multi-byte sequences. This is different from C's char (1 byte, ASCII only) and even from Java's char (2 bytes, UTF-16, can't hold all Unicode characters in a single char).
For ASCII-specific work, u8 with the b'...' syntax gives you single-byte characters: b'A' is 65u8. This is explicit about what you're doing—working with bytes, not Unicode characters—and prevents the kind of encoding confusion that plagues C programs when they encounter non-ASCII text.
From Primitives to Programs: Why This Foundation Matters#
Every struct you define is composed of these primitives. Every function parameter is one of these types (or a composite of them). Every computation your program performs ultimately operates on these atoms. Getting the foundation right—understanding that i32 is always 32 bits, that char is always Unicode, that bool is never an integer—means your understanding of everything built on top of them is solid.
At RantAI, our AI systems process diverse data types: integers for token IDs, floats for model weights, characters for text processing, booleans for feature flags. The fact that these types behave identically across our development machines (macOS), our CI servers (Linux x86), and our deployment targets (Linux ARM) means we never debug platform-specific type behavior. The types are the types. Everywhere. Always.
Practical Applications & Strategic Takeaways#
For newcomers: Use i32 for integers, f64 for floats, bool for conditions, and char for characters. These defaults are correct for 95% of use cases. Reach for specific sizes (i64, u8, f32) only when you have a specific reason.
For C/C++ veterans: Unlearn implicit conversions. bool is not int. char is not i8. There's no implicit narrowing, no silent truncation, no "the compiler will figure it out." Every conversion is explicit with as. This feels verbose at first and liberating after a week.
For performance engineers: f64 is the default for a reason—on modern hardware, f64 operations are often the same speed as f32 due to hardware FPU design. Use f32 only when memory bandwidth or SIMD width matters, not for "performance."
Our Commitment to Open Knowledge#
RantAI is committed to open education. Fundamental types are covered in Chapter 8, Sections 8.2.1–8.2.3 of our guide, "The Rust Programming Language," freely available online.
Explore these concepts further: https://trpl.rantai.dev
Support Our Mission & Get Your Handbook#
Get the Handbook on Amazon KDP: https://www.amazon.com/dp/B0DHCMD3F2
Get the Handbook on Google Play Books: https://play.google.com/store/books/details?id=INwfEQAAQBAJ
What surprised you most about Rust's primitive types coming from another language? The fixed sizes? The non-integer booleans? The 4-byte char? Share your "aha" moment below!
#RustLang #FundamentalTypes #Unicode #TypeSafety #RantAI #LearnRust #Primitives #Bool #Char #SystemsProgramming
Artikel berikutnya
Signed, Unsigned, and Character Literals: Why Rust Doesn't Let You Confuse Bytes with Letters