
無符號大小:一個持續五年的錯誤
C3 程式語言的開發者反思了過去五年將大小與長度預設為無符號整數的決定,並說明為何現在決定轉向以有符號整數為核心,以避免常見的程式錯誤並提升程式碼的清晰度。
背景
C3 是一門繼承 C 語言傳統的系統程式語言,其開發團隊在經過五年的實踐後,決定將陣列索引與長度等「尺寸類型」從無符號整數(Unsigned)改為有符號整數(Signed)。這項決策挑戰了 C、C++、Rust 及 Zig 等主流系統語言的慣例,旨在解決無符號整數在運算、比較及環狀緩衝區計算中常見的邏輯陷阱。
社群觀點
針對 C3 語言的這項轉變,Hacker News 社群展開了激烈的辯論,核心爭議在於「尺寸」在邏輯上不可能是負數,但「尺寸的運算」卻經常需要處理負值。支持有符號整數的觀點認為,無符號整數並非真正的「非負整數」,而是「模數運算(Modular Arithmetic)」,這導致在處理遞減迴圈或索引偏移時極易產生溢位陷阱。部分開發者指出,當索引運算錯誤時,有符號整數會產生負值,這在偵錯時比無符號整數溢位後產生的巨大正值更容易被察覺與攔截。甚至有觀點引用 C++ 之父 Bjarne Stroustrup 的看法,認為在處理如 std::span 等容器時,使用有符號整數運算其實是更為正確且安全的選擇。
然而,反對者則認為這是一種「因噎廢食」的設計。許多系統程式員強調,在底層開發、硬體通訊或高效能運算(HPC)領域,無符號整數能提供完整的位元範圍,這對於記憶體受限的環境至關重要。他們認為,如果一個數值在邏輯上永遠大於等於零,就應該使用能反映該特性的類型,而非為了規避 C 語言拙劣的隱式轉換規則而改用有符號整數。部分留言者批評,C3 的做法是試圖用類型系統來掩蓋語言設計上的缺陷,真正的解決方案應該是禁止危險的隱式轉換,或像 Rust 一樣提供明確的溢位檢查與顯式轉型 API。
此外,社群中也出現了超越「正負之爭」的深層討論。有開發者提出,現代語言應該擺脫直接對整數進行索引操作的低階思維,轉而推廣迭代器(Iterators)或不透明句柄(Opaque Handles)等高階抽象,從根本上消除索引運算的錯誤機會。另一派觀點則從形式科學出發,認為 C 語言中的無符號整數定義本身就存在矛盾,它既被當作非負整數使用,又在運算規則上被定義為同餘類(Residues),這種語義上的不一致才是導致開發者頻繁踩坑的主因。
延伸閱讀
- 論文:Dex: A Statically Typed, Functional Language for Array Processing,探討了更先進的陣列索引類型系統。
- 提案:P1428,關於 C++ 中 std::span 使用有符號整數作為尺寸類型的討論與 Bjarne Stroustrup 的觀點。
- 語言參考:Ada 與 Pascal 的子範圍類型(Subrange Types),展示了如何定義真正的非負整數類型。
相關文章