Copyright (慣C) 2015, 2017 宅色夫
"If I had eight hours to chop down a tree, I’d spend six hours sharpening my axe." – Abraham Lincoln
「如果我有 8 小時可以砍 1 棵樹,我會花 6 小時把斧頭磨利。」(類似漢語「工欲善其事,必先利其器」的精神) – 亞伯拉罕.林肯
「C 很彆扭又缺陷重重,卻異常成功。固然有歷史的巧合推波助瀾,可也的確是因為它能滿足於系統軟體實作的程式語言期待:既有相當的效率來取代組合語言,又可充分達到抽象且流暢,能用於描述在多樣環境的演算法。」
C is quirky, flawed, and an enormous success. Although accidents of history surely helped, it evidently satisfied a need for a system implementation language efficient enough to displace assembly language, yet sufficiently abstract and fluent to describe algorithms and interactions in a wide variety of environments. —— Dennis M. Ritchie
Jonathan Adamczewski 貼出經典著作《The C Programming Language》,然後評註說:
"C++: The Good Parts"
K&R C 的 "K" 即 Brian Kernighan 教授,而非 Ken Thompson。
David Brailsford 教授的訪談,從大型主機 (mainframe) 時代談起,早期的機器甚至不是 byte addressing,這使得高階程式語言和電腦硬體無法直接對應,而 C 語言恰好彌補系統層級程式設計的需求,再藉由 UNIX 作業系統的影響,改變今日我們所處的資訊世界。
C++ 可以美得令人不知所措 [source]
在 ISO/IEC 9899 (a.k.a C99 Standard) 中 5.1.2.2.1 內有提到 C Standard 要求 main 函式必須這樣寫
或者:
C++ 之父 Bjarne Stroustrup 的個人網頁內有個 FAQ 裡面有個問題叫 Can I write "void main()"?
然而在 C++ 與 C 的標準中從來沒出現過這樣的寫法,也就是說,void main()
這個寫法從來沒正確過
延伸閱讀
從一則笑話談起
葉秉哲博士的推文:「溯源能力是很重要的,才不會被狀似革新,實則舊瓶裝新酒或跨領域借用的『新觀念』所迷惑」
規格書 (PDF) 搜尋 "object",共出現 735 處
從第一手資料學習:大文豪寫作都不免要查字典,庸俗的軟體開發者如我們,難道不需要翻閱語言規格書嗎?難道不需要搞懂術語定義和規範嗎?
&
不要都念成 and,涉及指標操作的時候,要讀為 "address of"
C99 [3.14] object
region of data storage in the execution environment, the contents of which can represent values
在 C 語言的物件就指在執行時期,資料儲存的區域,可以明確表示數值的內容
很多人誤認在 C 語言程式中,(int) 7 和 (float) 7.0 是等價的,其實以資料表示的角度來看,這兩者截然不同,前者對應到二進位的 "111",而後者以 IEEE 754 表示則大異於 "111"
A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
關鍵描述!規範
void *
和char *
彼此可互換的表示法
C99 規格書的解說就比很多書本清楚,何必捨近求遠呢?
float *
has type "pointer to float". Its type category is pointer, not a floating type. The const-qualified version of this type is designated as float * const
whereas the type designated as "const float *
is not a qualified type — its type is "pointer to const qualified float" and is a pointer to a qualified type.struct tag (*[5])(float)
has type "array of pointer to function returning struct tag". The array has length five and the function has a single parameter of type float. Its type category is array.Understand more about C 提及若干肇因於不同的 C 語言標準,而使得程式碼行為不同的案例
為何 C 語言標準函式庫裡頭的函式名稱如此簡短?像是
最初連結器有 6 到 8 個字元的輸入限制!
Translation limits
6 significant initial characters in an external identifier
The Design and Evolution of C++ 一書對應的解說:
安裝 cdecl
程式,可以幫你產生 C 程式的宣告。
使用案例
會得到以下輸出:
把前述 C99 規格的描述帶入,可得:
如果你沒辦法用英文來解說 C 程式的宣告,通常表示你不理解!
cdecl
可以解釋 C 程式宣告的意義,比方說:
[ source ]
printf()
觀察的話,永遠只看到你設定的框架 (format string) 以內的資料,但很容易就忽略資料是否合法、範圍是否正確,以及是否看對地方printf()
大概是最早被記下來的函式,也困擾很多人,有意思的是,1960 年代初期 MIT 開發的 CTSS 作業系統 中,終端機命令就包含了 printf,後者一路從 Multics 和 Unix 繼承至今STMTDC PRINTF,11,T,T25
,前一行註解寫 "The following tables are the dictionaries of statement types"source: NASA before PowerPoint, 1961
Visual Studio Code (VS Code) 是 Microsoft 主導的開放原始碼專案,關於其操作說明和解說錄影可參見 共筆。
C 語言規格一直在變革,此刻最新的標準是 C17,其正式名稱為ISO/IEC 9899:2018,是在 2017 年準備、隔年發布的規範。C23 則是現行開發中規格的簡稱,預計在 2023 年進行投票並發佈新標準,稱為 C23。預計納入的特徵如下:
container_of
一類的巨集call_once
的支援,後者在並行 (concurrent) 環境中,得以確保某段程式碼始終只會執行一次char8_t
的支援,以 _t
結尾的慣例說明這由編譯器供應商提供的 typedef,這對 Unicode 更友好,於是我們可以書寫為 u8"💣"[0]
unreachable()
,讓編譯器得以進行更激進的最佳化,過往是 GNU extension= {}
取代 memset
函式的呼叫_Static_assert
,允許單一參數nodiscard
, maybe_unused
, deprecated
, 和 fallthrough
0b10101010
(很難想像 1970 年代發展的 C 語言,要到 2023 年或稍晚,才能直接指定二進位表示吧?) 和對應 printf() 的 %b
_BitInt(N)
and UnsignedBitInt(N)
types for bit-precise integers#elifdef
和 #elifndef
0xFFFF'FFFF
延伸閱讀: