Variables & Basic Types
Chapter 1 showed C trusting the programmer with the toolchain itself. This chapter shows the same trust applied to something Rust and Go both nail down precisely: how big a number actually is.
Declaring Variables
type name = value; — no let, no var, no inference. Every variable's type is written explicitly, every time.
The Basic Types
int— a whole numberfloat— single-precision floating pointdouble— double-precision floating point, the default for real workchar— a single byte, holding a small integer that's interpreted as a character (there is no separate "character" type underneath —chargenuinely is a small integer)
sizeof and Why Type Sizes Aren't Fixed
This is the chapter's real subject. In Rust, i32 is exactly 32 bits, everywhere, by definition — the type's name states its size as a language guarantee. In C, the standard only guarantees minimums: int is guaranteed to be at least 16 bits, but is commonly 32 bits on today's platforms — "commonly," not "guaranteed."
Writing genuinely portable C — code that behaves identically across every platform — means never assuming int is exactly 4 bytes, something Rust or Go code never has to worry about at all.
Fixed-Width Types via <stdint.h>
C99 added exactly the guarantee Rust and Go bake in by default — opt-in, not automatic.
Signed vs. Unsigned
Every integer type has a signed (default) and unsigned variant. This distinction hides a genuine asymmetry worth flagging now, well before Course 3's Undefined Behavior chapter covers it in full: unsigned overflow is well-defined — it wraps around (UINT_MAX + 1 becomes 0). Signed overflow is undefined behavior — the standard makes no promise about what happens at all, not even wraparound.
| Concept | Rust | C |
|---|---|---|
| Integer size guarantee | i32/i64 — exact, by definition | int/long — minimum only, platform-dependent |
| Opt-in exact width | n/a — always exact | int32_t/uint64_t via <stdint.h> |
| Unsigned overflow | panics in debug, wraps in release | always wraps — well-defined |
| Signed overflow | panics in debug, wraps in release | undefined behavior — no guarantee at all |
sizeof(int) looks like a function call, but sizeof is genuinely a compile-time operator — sizeof x (no parentheses) works too when applied directly to a variable. The parenthesized form is just the conventional style.
Coding Challenges
Write a program that prints the sizeof int, char, float, double, and long on your system, one per line, using %zu format specifiers.
📄 View solutionDeclare an unsigned char variable, set it to 255, add 1 to it, and print the result. Explain what happened and why it's well-defined behavior rather than a bug.
📄 View solutionExplain why int32_t from stdint.h is a genuinely different guarantee than plain int, and why Rust's i32 never needed an equivalent "opt-in exact width" type at all.
📄 View solutionChapter 2 Quick Reference
- int/float/double/char — explicit types, no inference
charis genuinely a small integer, not a distinct character type- The standard guarantees minimum sizes only —
intis commonly 4 bytes, never guaranteed <stdint.h>'sint32_t/uint64_t— opt-in, Rust/Go-style exact widths- Unsigned overflow — well-defined wraparound; signed overflow — undefined behavior, no guarantee
sizeofis an operator, not a function — parentheses are convention, not a requirement- Next chapter: operators, control flow, and C's historical lack of a true boolean type