C11标准委员会成员解读C语言新标准
導讀:C語言國際標準新的新草案之前已經公布,新標準提高了對C++的兼容性,并將新的特性增加到C語言中。此外支持多線程的功能也受到了開發者的關注,基于ISO/IEC TR 19769:2004規范下支持Unicode,提供更多用于查詢浮點數類型特性的宏定義和靜態聲明功能。根據草案規定,最新發布的標準草案修訂了許多特性,支持當前的編譯器。(背景:C編程語言的標準化委員會(ISO/IEC JTC1/SC22/WG14)已完成了C標準的主要修訂,該標準的早期版本于1999年完成,俗稱為“C99”。新標準在去年年底完成,也被稱為“C11”。)
本文作者Tom Plum是Plum Hall Inc.的技術工程副總監,也是C11和C++11標準委員會的成員,他在這篇文章里從語言集的atomic操作和線程原語開始探討了C語言的新特性,在文章末尾還討論了C11與C++兼容性問題。此外,在本文和它的姊妹篇里,作者還描述了C11的新功能、并發性、安全性和易用性等話題。
并發
C11的標準化了可能運行在多核平臺上的多線程程序的語義,使用atomic變量讓線程間通信更輕量。
頭文件<threads.h>提供宏、類型以及支持多線程的函數。下面是宏、類型和枚舉常量的摘要總結:
??? 宏:
??? 通過枚舉常量:
??? 線程枚舉常量:
??? 條件變量的函數:
??? 互斥函數:
??? 線程函數:
??? 特定于線程的存儲功能:
這些標準庫函數可能更適合作為易用的API的基礎而不是開發平臺來使用。例如,使用這些低級庫的函數時,很容易造成數據競爭,多個進程會不同步地對同一個位置的數據進行操作。C(和C++)標準允許任何行為,即使會發生爭用同一個變量x,哪怕會導致嚴重的后果。例如,多字節值x可能被一個線程修改部分字節,而另一個線程又會修改別的部分(值撕裂),或者產生一些其它的副作用。
下面一個簡單的示例程序,它包含一個數據競爭,其中64位的整數x會同時被兩個線程改動。
如果你的應用已經符合C11的標準,并且將它在一個32位的機器編譯過了(在64位機器里long long類型會占用兩倍以上的存儲周期),你將會看到數據競爭的結果,得到像下面亂碼一樣的輸出:
傳統的解決方案是通過創建一個鎖來解決數據競爭。然而,用atomic數據有時會更高效。加載和存儲atomic類型循序漸進、始終如一。特別是如果線程1存儲了一個值名為x的atomic類型變量,線程2讀取該值時則可以看到之前在線程1中運行的所有其它存儲(即使是非atomic對象)。(C11和C++11標準還提供其他內存一致性的模型,雖然專家提醒要遠離它們。)
新的頭文件<stdatomic.h>提供了很多命名類和函數來操作atomic數據的大集。例如,atomic_llong就是一個為操作atomic long long整數的類型。所有的整數類都提供了相似的命名。該標準包括一個ATOMIC_VAR_INIT(n)宏,用來初始化atomic整數,如下:
之前的數據競爭的例子可以通過定義x為一個atomic_llong類型的變量解決。簡單地改變一下上述例子中聲明x的那行語句:
通過使用這樣的atomic變量,代碼在運行中不會出現任何數據競爭的問題。
注意關鍵字
C委員會并不希望在用戶命名空間里創建新的關鍵字,每個新的C版本都一直在避免出現不兼容之前版本C程序的問題。相比之下,C++委員會(WG21)更喜歡創造新的關鍵字,例如:C++11定義一個新的thread_local關鍵字來指定一個線程的本地靜態存儲,C11使用_Thread_local來代替,在C11新的頭文件<threads.h>中有一個宏定義來提供normal-looking name:
下面我將假設你已經引入例如適當的頭文件,所以我會顯示normal-looking name。
thread_local存儲類
新thread_local存儲類為每個線程提供一個單獨的靜態存儲,并且在線程運行之前初始化。但有沒有保障措施來防止你捕獲一個thread_local變量的地址,并把它傳遞給其他線程,然后明確實現(即,不便攜/不可移植),每個線程在thread_local都有它自己的errno存儲副本。
線程可選
C11已指定為多種特色為可選功能,例如:如果它明確實現了一個名為 _ _STDC_NO_THREADS_ _ 的宏,就不會提供一個頭名為<threads.h>的頭文件,也不可能在其中定義任何函數。
設計準則
作為通則,WG21委托Bjarne Stroustrup整體設計和進化的責任,不明白的話可以在網上搜索“camel is a horse designed by committee”。然而,有一個WG14和WG21同樣遵循的設計原則:不要給任何系統編程語言比我們(C/C++)更高效的機會!
一些與會者(稱他們為“A組”)認為atomic數據仍將是一個很少使用的專業性功能,但其他人(稱他們為“B組”)認為,atomic數據將成為一個重要的功能,至少會在一種系統編程語言中被應用。
在過去的幾十年里,很多更高級別的語言都是基于C語言創建的(Java,C#,ObjectiveC,當然,也包括C++)和C++子集或超集(如D和嵌入式C++)。許多參與WG14和WG21的公司已經決定使用這些語言作為自己的應用的編程語言(稱他們為“C組”)。這些公司之所以選擇C++作為他們的上層應用程序的語言,通常是因為C足夠穩定(或者說是因為WG21控制其標準化),而選擇其他語言的公司(稱他們為“D組”)通常認為C是他們所使用的高級語言非常重要的基石。
有了這些背景,我可以得出一個C11中atomic進化的理由。C++11中對atomic的設計充分運用了模板。比如atomic<T>是獲得任何一種類型T的簡單且常用的方法。即使T是一個類或結構,那么無論T*指向哪兒,atomic<T*>都會保存類型信息,但是,幾年來,C語言的設計依然只用了幾十種命名類型(如上所示的atomic_llong)。這樣做的主要優點在于:它不需要編譯器做任何改變。它能夠實現一個僅庫的解決方案,會在最低水平調用系統依賴的原生函數。然而命名類型的解決方案干撓了為C結構或者T*指針創建atomic(無論多么小)。主要因為B組和D組的意見,WG14決定要求C11編譯器為任何類型的T識別atomicT。
后來也有一個WG14內部的關于編譯器識別atomicT語法的爭論。一種使用atomic-parenthesis的解決方案因為和C++良好的兼容性而被推動。Let _Atomic(T)成為了指定atomicT的語法。同樣的源程序能夠簡單地在C++定義宏中編譯。
另一種相反的觀點認為應該創建新的類限制符(類似于C99的_Complex的解決方案);使用"atomic-space"語法,atomic T類型應該被寫為“_Atomic T”。使用這種語法的程序型的程序無法立刻被當作C++來編譯。(無兼容性宏,本質上看起來像atomic-parenthesis的方法)。
獲取C11標準
新標準可以在webstore.ansi.org查看(或者搜索"ISO/IEC 9899:2011")。現在已經有了PDF文檔,但是需要支付$285(和C++2011一樣)才可以使用。一旦這些標準被ANSI采納為美國國家標準,價格將下降至$30左右。
你可以定期檢查此頁面的部分,我及時檢查草案的狀態,如果您填寫了這個Web表單,將會在C11和C++11被ANSI采用為標準時獲得電子郵件通知。也可以通過tplum@plumhall.com聯系我,非常感謝來自Pete Becker(C++2011標準的項目編輯)的建設性建議。
原文鏈接:drdobbs.com
更多關于C11的變更可以參考維基百科
相關文章:
ISO發布C語言標準新版本
C語言中史上最愚蠢的Bug
如何創建比C語言更快的編程語言?
總結
以上是生活随笔為你收集整理的C11标准委员会成员解读C语言新标准的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: uni-app实现上拉加载更多
- 下一篇: uni-app实现上传多张照片