Unsigned Sizes: A Five Year Mistake

· coding · Source ↗

TLDR

  • C3 is switching to signed sizes by default after five years, concluding unsigned sizes cause more bugs than they prevent in systems languages.

Key Takeaways

  • Unsigned sizes force pervasive signed/unsigned casts or implicit promotion rules, both of which silently hide arithmetic bugs.
  • C3’s rule promoting int + uint to int broke down at division and modulo, producing plausible but wrong results near INT_MAX.
  • Ring buffer offset math with unsigned types produces wrong wrap behavior that the compiler cannot detect; signed types make the error obvious via negative values.
  • Go and Java both chose signed sizes deliberately; Go’s designers knew the unsigned cost and rejected it anyway.
  • C3 0.8.0 renames the signed size type to sz and drops implicit signed/unsigned conversion entirely, making unsigned use visibly exceptional.

Hacker News Comment Review

  • Commenters are split: systems programmers with embedded or low-level backgrounds push back, arguing full word range and modular arithmetic are genuinely needed and signed sizes just shift boundary problems rather than eliminate them.
  • The Rust experience is disputed: several commenters say usize causes minimal friction if you keep value origins consistent with destination types, contradicting the article’s cast-proliferation argument.
  • A recurring caveat is that signed overflow is UB in C/C++, so the “negative value signals wrongness” argument only cleanly holds in languages like C3 with defined two’s complement behavior.

Notable Comments

  • @cperciva: calls the design rationale weak, noting compiler warnings already flag tautologous and mixed-sign comparisons without language-level changes.
  • @lerno: key asymmetry is that unsigned overflow yields a plausible wrong value while signed overflow yields an obviously wrong negative one.

Original | Discuss on HN