A Rust-first systems programmer summarizes the sharp contrasts and pitfalls encountered when learning C, highlighting a string of language oddities rather than offering a tutorial. Key differences include booleans (original C used integers; C99 introduced stdbool.h where true/false are macros expanding to 1/0, and C23 finally made booleans primitives), and string representation: C uses null-terminated char arrays instead of fat pointers, so every string needs an extra byte for '\0', interior nulls break C string functions, and forgetting the terminator causes out-of-bounds reads. Integer widths are target-dependent (e.g., long is 64-bit on Unix but 32-bit on Windows), so the recommendation is to use the fixed-width types from stdint.h for portability. A concrete reverse-string example shows the need to allocate len+1 bytes and manage the terminator manually.
The write-up also covers C’s weaker ergonomics around errors and memory: error handling relies on magic return values, null pointers, and errno rather than algebraic Result types, leaving checks entirely to the programmer. Field access distinguishes between value (.) and pointer (->) syntax. Arrays decay to pointers when passed to functions, leading to surprising sizeof() results and compiler warnings. There are no references or borrow checking - only raw pointers and pointer arithmetic - so memory safety and manual bookkeeping replace many of Rust’s compile-time guarantees.
Summary generated by AI from the linked article. hn.today is not affiliated with Hacker News or Y Combinator.