1. 程式人生 > >什麽是 C 和 C ++ 標準庫?

什麽是 C 和 C ++ 標準庫?

lec 內存占用 串處理 函數 背景 成員 流程 出版 contain

簡要介紹編寫C/C ++應用程序的領域,標準庫的作用以及它是如何在各種操作系統中實現的。

我已經接觸C++一段時間了,一開始就讓我感到疑惑的是其內部結構:我所使用的內核函數和類從何而來? 誰發明了它們? 他們是打包在我系統中的某個地方嗎? 是否存在一份官方的C ++手冊?

在本文中,我將通過從C和C ++語言的本質到實際實現來嘗試回答這些問題。

C和C++是如何制訂的

當我們談論C和C++時,實際上是指一組定義(程序)語言應該做些什麽,如何表現,應該提供哪些功能的規則。C/C++的編譯器為了處理C/C++編寫的源代碼必須跟隨著這些規則,並生成二進制應用程序。聽起來非常接近於HTML:瀏覽器遵循著一組指令,所以它們可以以明確的方式來渲染網頁。


與HTML一樣,C和C++的規則都是理論上的。國際標準化組織(ISO)的一大群人每年都會聚集幾次來討論和定義語言規則。沒錯,C和C++是標準化的東西。他們最終都會得到一本官方的叫標準的書,你可以從他們的網站中購買。隨著語言的發展新的papers(指官方的叫標準的書)會被發布,每一次都定義一個新的標準。這就是為什麽我們會有不同的C和C++版本的原因:C99, C11, C++03, C++11, C++14等等,數字與出版/發布年份相符。

技術分享圖片 Tot_ziens 翻譯於 4周前 2人頂 翻譯得不錯哦!

這些標準都市非常詳細和有技術新的文檔:我不會把它們當作手冊。通常會分為兩部分:

1.C/C++的功能和特性;

2.C/C++的API--開發人員可以用於他們的C/C++程序的一個類、函數和宏的集合。它也被稱為標準庫。

例如,這裏有個來自於C標準庫第一部分的摘選,它定義了main函數的結構:

技術分享圖片

1.main的定義,程序啟動時調用的函數。

這是另外一個來自與同樣標準的摘錄,描述了CAPI的成員--fmin函數:

技術分享圖片

2.在math.h偷文件中定義min函數。

如你所見,幾乎沒涉及到代碼。有人必須閱讀標準並將其轉換成計算機可以消化的東西。這是工作於編譯器和(功能)實現上人們所做的:前者是一種可以讀取和處理C和c++源文件的工具,後者將標準庫轉換為代碼。我們來深入了解一下。。

C標準庫

C標準庫也稱為ISO C庫,是用於完成諸如輸入/輸出處理、字符串處理、內存管理、數學計算和許多其他操作系統服務等任務的宏、類型和函數的集合。它是在C標準中(例如C11標準)中定義的。其內容分布在不同的頭文件中,比如上面我所提到的math.h。

C++標準庫

和C標準庫的概念類似,但僅針對C ++。C++標準庫是一組C++模板類,它提供了通用的編程數據結構和函數,如鏈表、堆、數組、算法、叠代器和任何其他你可以想到的C++組件。C ++標準庫也包含了C標準庫,並在C++標準中進行了定義(例如C++ 11標準)。

實現C/C++標準庫

我們從這裏開始討論真正的代碼了。從事於標準庫實現的開發者閱讀官方的ISO規範並將其轉化為代碼。他們必須依賴其操作系統所提供的功能(讀/寫文件,分配內存,創建線程,......所有這些被稱為系統調用),因此每個平臺都有其自己的標準庫實現。 有時它是系統內核的一部分,有時它是作為一個附加組件 - 編譯器 - 必須單獨下載。

GNU/Linux版實現

GNU C庫,也稱為glibc, 是C標準庫的GNU項目實現。並非所有的標準C函數都可以在glibc中找到:大多數數學函數實際上是在libm庫中實現的,這是一個獨立的庫。

截至今天,glibc是Linux上使用最廣泛的C庫。 然而,在90年代期間,有一段時間裏,glibc有一個競爭對手稱為Linux libc(或者簡稱libc),它是由glibc 1.x的一個分支產生的。在一段時間裏,Linux libc是許多Linux發行版中的標準C庫。

經過多年的發展,glibc竟然比Linux libc更具優勢,並且所有使用它的Linux發行版都切換回了glibc。所以,如果你在你的磁盤中找到一個名為libc.so.6的文件,請不要擔心:它是現代版的glibc。為了避免與之前的Linux libc版本混淆,版本號增加到了6(他們無法將其命名為glibc.so.6:所有Linux庫都必須以lib前綴打頭)。

另一方面,C++標準庫的實現位於libstdc++或GNU標準C++庫中。這是一個正在進行的在GNU/Linux上實現標準C++庫的項目。一般來說,所有常規的Linux發行版都默認使用libstdc++。

Mac和iOS版實現

在Mac和iOS上,C標準庫的實現是libSystem的一部分,libSystem是位於/usr/lib/libSystem.dylib中的核心庫。LibSystem包含其他組件,如數學庫、線程庫和其他底層實用程序。

關於C++標準庫,在OS X Mavericks(V10.9)之前的Mac上,libstdc++是默認選項。這在現代的基於Linux的系統上可以找到的同樣的實現。自OS X Mavericks開始,Apple切換到使用libc++,這是LLVM項目——Mac官方編譯器框架——所引入的GNU libstdc++標準庫的替代。

IOS開發者可以使用iOS SDK(軟件開發工具包)來訪問標準庫,它是一系列允許創建移動應用程序的工具。

Windows版實現

在Windows上,標準庫的實現一直嚴格限定在Visual Studio中,它是微軟官方的編譯器。他們通常稱之為C/C++運行時庫(CRT),並且它涵蓋了c/c++二者的實現。

在最開始,CRT被實現為CRTDLL.DLL庫(我猜,當時沒有可用的C++標準庫)。從Windows 95開始,Microsoft開始將其遷移到MSVCRT [版本號] .DLL(MSVCR20.DLL,MSVCR70.DLL等)之上,據推測也包含C++標準庫。在1997年左近,他們決定將文件名簡化為MSVCRT.DLL,這不幸導致了令人討厭的DLL混亂。這就是為什麽從Visual Studio 7.0版開始,他們切換回每個版本使用單獨的DLL了。

Visual Studio 2015引入了深度的CRT重構。C/C ++標準庫的實現遷移到一個新庫,Universal C運行時庫 (Universal CRT或UCRT),編譯為UCRTBASE.DLL。 UCRT目前已經成為Windows組之一,從Windows 10開始作為操作系統的一部分提供。

Android版實現

Bionic是Google為其Android操作系統所編寫的C標準庫實現,它直接在底層使用。 第三方開發者可以通過Android原生開發工具包(NDK)訪問Bionic,該工具集允許你使用C和C++代碼編寫Android應用程序。

在 C++ 端, NDK提供了很多版本的實現:

  • libc++,從從Lollipop開始的官方安卓系統和現代Mac操作系統都將其作為C++標準庫使用。從NDK發布17版本開始,它將成為NDK中唯一可用的C++標準庫實現;

  • gnustl,libstdc++的別名,這兩者在GNU/linux是同一個庫。這個庫的已被棄用,它將在NDK發布18中刪除;

  • STLport,由STLport項目編寫的C++標準庫的第三方實現,自2008年以來一直處於不活躍狀態。與gnustl一樣,STLport將在NDK發布18中移除。

我能使用不同版本的實現代碼來替代默認實現嗎?

如果你正在使用資源非常有限的系統,則通常需要引用C標準庫的不同實現。比如,uClibc-ng, musl libc和diet libc等等,所有這些都適用於嵌入式Linux系統的開發,提供更小的二進制文件和更少的內存占用。

C++標準庫也有不同的實現版本:Apache C++標準庫,uSTL以及EASTL等等。後面兩個實際上僅關註模板部分,而不是完整的庫,並且他們是在速度優先的情況下開發的。Apache版本的庫註重的是可移植性。

如果我們脫離了標準庫怎麽辦?

不使用標準庫很簡單:只要在你的程序中不引入它們的任何一個頭文件,你的工作就完成了。然而,為了讓這個操作更有意義一些,你需要通過一些提供的系統調用使用某種方法與操作系統互動。就像我之前說的,這就是標準庫中的函數/方法在底層實現的時候所使用的。很可能你也會不得不調用這些方法來與硬件設備交互。
如果對你來說這聽起來很讓人激動,有些人已經開始在網上嘗試在不導入標準庫的情況下創建工作流程。因為你依賴於一個特定操作系統所提供的函數,這種方式會喪失可移植性。然而通過使用這種艱難的方式,肯會讓你學到更多,而且讓你更好的理解當你所做的事情,即使是在使用高級庫的時候。
除了知識,當你在嵌入式操作系統上面工作的時候你不會想去引入標準庫:因為代碼不需要移植,在有限的內存中每個字節都很重要,這會讓你更加精準的寫代碼。另一個使用背景就是demoscene,在這裏人們盡量有限的程序的二進制大小中去保留高質量的音視頻——4K仍然不是最小值:一些demoparties使用1K,256字節,64字節或者甚至32字節來競爭。在那裏不允許使用標準庫!

https://www.oschina.net/translate/c-c-standard-library?lang=chs&page=1#

什麽是 C 和 C ++ 標準庫?