首先說明,我google了半天,想找到英文的關於這個資料,但是實在找不到,只好轉載國人的討論。
CRT原先是指Microsoft開發的C Runtime Library,用於作業系統的開發及運行。後來在此基礎上開發了C++ Runtime Library,所以現在CRT是指Microsoft開發的C/C++ Runtime Library。在VC的CRT/SRC目錄下,可以看到CRT的源碼,不僅有C的,也有C++的。
CRT原先的目的就是支援作業系統的運行。因為Windows作業系統除彙編部分外,都是用C/C++編寫的,所以核心及許多關鍵服務都在CRT上運行(它們都採用dll技術動態連結)。此外,用 VC編寫的C/C++程式也用到它們(可以動態連結,也可以靜態連結,前者運行時需要系統中已安裝CRT的dll,後者不需要)。可以說,CRT就是 Microsoft編寫Windows時使用的低層類庫。然後,它又被當作C++標準庫的一個實現包含在了VC系列中;我們在VC中使用的C++標準庫,其實就是CRT的一個真子集(少了C++標準所不包含的代碼,特別是大量的低層C代碼)
至於CRT與WINDOWS API的關係,與許多人理解的相反,WINDOWS API作為Windows的一部份,是在CRT的基礎上開發的。你可以將Windows(及其API)看作一個項目,而這個項目使用的語言是彙編/C/C ++,使用的類庫就是CRT。所以,離開CRT,Windows API也無法使用的。
C++標準,是C++的通用語言規範,指導所有C ++使用者。而CRT的其中一部分可以看作是Microsoft開發的一個C++標準庫實現(其實也確實如此,Microsoft在開發CRT時,參考了正在標準化過程中的C++語言規範)。它與C++標準有一定的差距,部分原因是,在C++沒有完成標準化之前,CRT已經開發並投入使用了。為了向下相容以前的Windows代碼,早期的CRT與C++標準總有一定的差距。但是CRT確實在不斷的改進中。VC6帶的CRT與C++標準還有比較大的差距,而 VC8的幾乎完全符合C++標準了。
綜上,CRT(Microsoft's C/C++ Runtime Library)的一個真子集(主要是C++ Runtime Library)是一個符合(或至少是企圖符合)C++標準的C++庫。而Windows API(以及Windows的其他許多部分)都是在CRT的基礎上開發的。
除了以上介紹的,在使用CRT的過程中,還需要瞭解的是:
1、CRT的一些組成部分也調用了Windows API。這可能就是有人認為CRT是建立的Windows API基礎上的原因。但是實際上,這一部分剝離CRT沒有任何的問題。只不過Microsoft將在Windows平台上可以使用的C/C++低層庫都加入到CRT中。因此,CRT中很大一部分是作業系統平台無關的(原始的CRT),是開發Windows本身及其上一切的基礎。它們也可以作為一個C/C+ +庫在其他動作系統平台上使用。還有一部分,則是和Windows緊密綁定的,調用Windows API來實現的,可以看作擴充的CRT。之所以將這兩部分放在一起,是因為它們都是開發Windows作業系統所需要的,也因為它們也都是Windows 平台上的C/C++程式員所需要的。這種複雜關係是Microsoft的人為因素造成的,不能因此認為CRT是建立在Windows或Windows API基礎上的。
2、CRT的大部分內容是跨硬體平台的,但是也有一些部分,是直接用彙編寫成、基於硬體平台、並根據特定硬體平台做的最佳化(而不是將產生機器碼的責任完全交給編譯器)。如早期對Indel的x32做了最佳化,現在由加入對AMD64的最佳化,這部分則是不跨硬體平台的。
關於ATL
ATL是建立在CRT上的,如果你看了ATL的源碼就知道了。至於不用連結,是因為ATL庫靜態連結了CRT,所以它可以在CRT之外運行。類似這樣的誤解在於混淆了作為低層基本庫的CRT和作為產品而附帶在VC中的CRT。雖然這兩者是同樣的代碼,但是概念是不一樣的。
在編寫作業系統時,你需要一個合適的低層庫,以便完成一些基本的、多次重複的工作。於是,就有了CRT。在最低層的時候,根本連dll這個概念都沒有的,所以CRT的原始碼只能做成lib,被靜態連結。然後,隨著Windows越做越複雜,Microsoft提出了API的概念,它提供Windows開發人員一組介面,可以直接操作Windows,這就是Windows API了。當然,Windows API也是在CRT之上編寫的。
接著, Microsoft想給予C/C++程式員以足夠的支援,除了原始CRT之外,還要增加在Windows平台上編程所特有的東西,如thread等等。這些東西都是和平台相關的,只能建立在Windows API上。而這些新增內容,也被放進了CRT中。此時,CRT不僅僅包含最低層平台無關的代碼,還包括平台相關的部分。如你調用CRT的 _beginthread,其實內部調用了Windows API的CreateThread。加入這些東西後,CRT仍然被用作編寫作業系統;但是顯然,那些調用了Windows API的部分已經失去移值性了。
然後,CRT被封裝成產品,隨編譯器一起發布。此時CRT產品的LIB和DLL都是Windows格式的,你不能在Windows以外的平台上使用EXE或DLL吧,這就是CRT和CRT產品的區別。Windows API的產品,或是Windows的其他許多組成部分也是一些LIB/DLL檔案,這些都是表面的東西,是與Windows綁定在一起的。但是,如果你認為是先有Windows或Windows API,才有CRT的,那你就本末倒置了。除非你對CRT的定義就是那些LIB/DLL產品,而不包括用來產生它們的代碼。
就象C++編譯器用來編譯用C++寫的編譯器自身一樣,Windows(及其上的編譯器)用來作為平台開發和編譯CRT,並也用CRT來寫Windows自身(當然第一個CRT和第一個用來編譯Windows的編譯器不是在Windows上開發的)。就象“我”也可以先寫一個類庫,然後在它基礎上寫一個作業系統,在這個作業系統上進一步擴充這個類庫,然後將它配合編譯器發布出去,發展一些我的作業系統的支援者,順便再賺點收入。或者以另一種模式發布另一個庫(只是我在原來那個庫上開發的一個產品,由於我獨立地發布這個新庫,許多人會不知道這個新庫與舊庫的關係。這很好,因為編程本身就是盡量隱藏細節,盡量做到對使用者透明的),吸引不同風格的開發人員。這樣我的付出得到了最大的回報——由於我沒有發佈動作系統的原始碼,所以許多使用者認為我不僅做了系統,還做了編譯器,還開發了一個類庫。做了那麼多事,回報是應該的。其實他們不知道,類庫是編寫作業系統所必須的,編譯器也是必須的,這些必須的東西卻可以在作業系統之外獲得更多的回報,真是太完美了!這是什嗎?這就是商業精神!當然這些誤解對我是有好處的,我就不必到處宣揚真相了。反正我把類庫的源碼都發布了,也沒有騙過人吧。我不過是在那個原始類庫中加進了一些與我的作業系統相關的東西,以方便在我的系統上編寫程式的人們,這是我的好心吧;至於有人可能產生進一步的誤解,就不是我需要考慮的了……
所以還是看看CRT的源碼吧——看看那些針對硬體平台的彙編;看看VC的標準C++庫和CRT關係;再看看其他動作系統的原始碼,想想CRT中的哪些部分可以支援用來寫作業系統,而如果我自己寫系統,又需要哪些東西;甚至你可以看看DOS的原始碼,想想和CRT的相似性,以及曆史淵源。可惜不能看到Windows的原始碼,否則一切就清楚了。
最後再說一句,C++當然不是Microsoft的專利。但是Microsoft選擇了C++,並取得了成功,這是肯定的了:象CRT,象VC,象Windows,象Office,象 SQLServer......這一方面說明了C++的優勢,一方面也是Microsoft自身的因素在起作用。然後,它當然要緊抓C++的大旗,大力宣揚它自己的C++,並排斥其他的C++。這就是帝國的“風範”了。所以對Microsoft,總是即恨且愛,總希望哪天它會良心發現——當然這隻是幻想罷了。不過,肯定該肯定的,否定該否定的,總是應該的。但就產品而言,Microsoft不是最好的,但大多都是最成功的,在看到它的不足的同時,也要看到它的優點。存在的即使不是合理的,也一定有它的合理性。所以,不能簡單用一兩句話評價Microsoft及它的成功。惟有一點是可以肯定的,它決定選擇C ++,真是太英明了!
-------------------------------------------
C Runtime Library
對於上面的這個太頭困惑了很久,現在轉貼一張
抄來的 共同學習哈
***************************************
1)執行階段程式庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程式運行時需要這些庫中的函數.
2)C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程式控制制,資料類型等);所以,C 語言核心開發出來之後, Dennis Ritchie 和 Brian Kernighan 就用 C 本身重寫了 90% 以上的 UNIX 系統函數,並且把其中最常用的部分獨立出來,形成標頭檔和對應的 LIBRARY,C run-time library 就是這樣形成的。
3)隨後,隨著 C 語言的流行,各個 C 編譯器的生產商/個體/團體都遵循老的傳統,在不同平台上都有相對應的 Standard Library,但大部分實現都是與各個平台有關的。由於各個 C 編譯器對 C 的支援和理解有很多分歧和微妙的差別,所以就有了 ANSI C;ANSI C (主觀意圖上)詳細的規定了 C 語言各個要素的具體含義和編譯器實現要求,引進了新的函式宣告方式,同時訂立了 Standard Library 的標準形式。所以C執行階段程式庫由編譯器生產商提供。至於由其他廠商/個人/團體提供的標頭檔和庫函數,應當稱為第三方 C 運行庫(Third party C run-time libraries)。
4)C run-time library裡面含有初始化代碼,還有錯誤處理代碼(例如divide by zero處理)。你寫的程式可以沒有 math庫,程式照樣運行,只是不能處理複雜的數學運算,不過如果沒有了C run-time庫,main()就不會被調用,exit()也不能被響應。因為C run-time library包含了C程式啟動並執行最基本和最常用的函數。
5)到了 C++ 世界裡,有另外一個概念:Standard C++ Library,它包括了上面所說的 C run- time library 和 STL。包含 C run-time library 的原因很明顯,C++ 是 C 的超集,沒有理由再重新來一個 C ++ run-time library. VC針對C++ 加入的Standard C++ Library主要包括:LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB
6)Windows環境下,VC提供的 C run-time library又分為動態執行階段程式庫和靜態執行階段程式庫。
動態執行階段程式庫主要是DLL庫檔案msvcrt.dll(or MSVCRTD.DLL for debug build),對應的Import library檔案是MSVCRT.LIB(MSVCRTD.LIB for debug build)
靜態執行階段程式庫(release版)對應的主要檔案是:
LIBC.LIB (Single thread static library, retail version)
LIBCMT.LIB (Multithread static library, retail version)
msvcrt.dll提供幾千個C函數,即使是像printf這麼低級的函數都在msvcrt.dll裡。其實你的程式運行時,很大一部分時間時在這些運行庫裡運行。在你的程式(release版)被編譯時間,VC會根據你的編譯選項(單線程、多線程或DLL)自動將相應的執行階段程式庫檔案 (libc.lib,libcmt.lib或Import library msvcrt.lib)連結進來。
編譯時間到底哪個C run-time library聯入你的程式取決於編譯選項:
/MD, /ML, /MT, /LD (Use Run-Time Library)
你可以VC中通過以下方法設定選擇哪個C run-time library聯入你的程式:
To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box.
從程式可移植性考慮,如果兩函數都可完成一種功能,選執行階段程式庫函數好,因為各個 C 編譯器的生產商對標準C Run-time library提供了統一的支援.
首先說明,我google了半天,想找到英文的關於這個資料,但是實在找不到,只好轉載國人的討論。
CRT原先是指Microsoft開發的C Runtime Library,用於作業系統的開發及運行。後來在此基礎上開發了C++ Runtime Library,所以現在CRT是指Microsoft開發的C/C++ Runtime Library。在VC的CRT/SRC目錄下,可以看到CRT的源碼,不僅有C的,也有C++的。
CRT原先的目的就是支援作業系統的運行。因為Windows作業系統除彙編部分外,都是用C/C++編寫的,所以核心及許多關鍵服務都在CRT上運行(它們都採用dll技術動態連結)。此外,用 VC編寫的C/C++程式也用到它們(可以動態連結,也可以靜態連結,前者運行時需要系統中已安裝CRT的dll,後者不需要)。可以說,CRT就是 Microsoft編寫Windows時使用的低層類庫。然後,它又被當作C++標準庫的一個實現包含在了VC系列中;我們在VC中使用的C++標準庫,其實就是CRT的一個真子集(少了C++標準所不包含的代碼,特別是大量的低層C代碼)
至於CRT與WINDOWS API的關係,與許多人理解的相反,WINDOWS API作為Windows的一部份,是在CRT的基礎上開發的。你可以將Windows(及其API)看作一個項目,而這個項目使用的語言是彙編/C/C ++,使用的類庫就是CRT。所以,離開CRT,Windows API也無法使用的。
C++標準,是C++的通用語言規範,指導所有C ++使用者。而CRT的其中一部分可以看作是Microsoft開發的一個C++標準庫實現(其實也確實如此,Microsoft在開發CRT時,參考了正在標準化過程中的C++語言規範)。它與C++標準有一定的差距,部分原因是,在C++沒有完成標準化之前,CRT已經開發並投入使用了。為了向下相容以前的Windows代碼,早期的CRT與C++標準總有一定的差距。但是CRT確實在不斷的改進中。VC6帶的CRT與C++標準還有比較大的差距,而 VC8的幾乎完全符合C++標準了。
綜上,CRT(Microsoft's C/C++ Runtime Library)的一個真子集(主要是C++ Runtime Library)是一個符合(或至少是企圖符合)C++標準的C++庫。而Windows API(以及Windows的其他許多部分)都是在CRT的基礎上開發的。
除了以上介紹的,在使用CRT的過程中,還需要瞭解的是:
1、CRT的一些組成部分也調用了Windows API。這可能就是有人認為CRT是建立的Windows API基礎上的原因。但是實際上,這一部分剝離CRT沒有任何的問題。只不過Microsoft將在Windows平台上可以使用的C/C++低層庫都加入到CRT中。因此,CRT中很大一部分是作業系統平台無關的(原始的CRT),是開發Windows本身及其上一切的基礎。它們也可以作為一個C/C+ +庫在其他動作系統平台上使用。還有一部分,則是和Windows緊密綁定的,調用Windows API來實現的,可以看作擴充的CRT。之所以將這兩部分放在一起,是因為它們都是開發Windows作業系統所需要的,也因為它們也都是Windows 平台上的C/C++程式員所需要的。這種複雜關係是Microsoft的人為因素造成的,不能因此認為CRT是建立在Windows或Windows API基礎上的。
2、CRT的大部分內容是跨硬體平台的,但是也有一些部分,是直接用彙編寫成、基於硬體平台、並根據特定硬體平台做的最佳化(而不是將產生機器碼的責任完全交給編譯器)。如早期對Indel的x32做了最佳化,現在由加入對AMD64的最佳化,這部分則是不跨硬體平台的。
關於ATL
ATL是建立在CRT上的,如果你看了ATL的源碼就知道了。至於不用連結,是因為ATL庫靜態連結了CRT,所以它可以在CRT之外運行。類似這樣的誤解在於混淆了作為低層基本庫的CRT和作為產品而附帶在VC中的CRT。雖然這兩者是同樣的代碼,但是概念是不一樣的。
在編寫作業系統時,你需要一個合適的低層庫,以便完成一些基本的、多次重複的工作。於是,就有了CRT。在最低層的時候,根本連dll這個概念都沒有的,所以CRT的原始碼只能做成lib,被靜態連結。然後,隨著Windows越做越複雜,Microsoft提出了API的概念,它提供Windows開發人員一組介面,可以直接操作Windows,這就是Windows API了。當然,Windows API也是在CRT之上編寫的。
接著, Microsoft想給予C/C++程式員以足夠的支援,除了原始CRT之外,還要增加在Windows平台上編程所特有的東西,如thread等等。這些東西都是和平台相關的,只能建立在Windows API上。而這些新增內容,也被放進了CRT中。此時,CRT不僅僅包含最低層平台無關的代碼,還包括平台相關的部分。如你調用CRT的 _beginthread,其實內部調用了Windows API的CreateThread。加入這些東西後,CRT仍然被用作編寫作業系統;但是顯然,那些調用了Windows API的部分已經失去移值性了。
然後,CRT被封裝成產品,隨編譯器一起發布。此時CRT產品的LIB和DLL都是Windows格式的,你不能在Windows以外的平台上使用EXE或DLL吧,這就是CRT和CRT產品的區別。Windows API的產品,或是Windows的其他許多組成部分也是一些LIB/DLL檔案,這些都是表面的東西,是與Windows綁定在一起的。但是,如果你認為是先有Windows或Windows API,才有CRT的,那你就本末倒置了。除非你對CRT的定義就是那些LIB/DLL產品,而不包括用來產生它們的代碼。
就象C++編譯器用來編譯用C++寫的編譯器自身一樣,Windows(及其上的編譯器)用來作為平台開發和編譯CRT,並也用CRT來寫Windows自身(當然第一個CRT和第一個用來編譯Windows的編譯器不是在Windows上開發的)。就象“我”也可以先寫一個類庫,然後在它基礎上寫一個作業系統,在這個作業系統上進一步擴充這個類庫,然後將它配合編譯器發布出去,發展一些我的作業系統的支援者,順便再賺點收入。或者以另一種模式發布另一個庫(只是我在原來那個庫上開發的一個產品,由於我獨立地發布這個新庫,許多人會不知道這個新庫與舊庫的關係。這很好,因為編程本身就是盡量隱藏細節,盡量做到對使用者透明的),吸引不同風格的開發人員。這樣我的付出得到了最大的回報——由於我沒有發佈動作系統的原始碼,所以許多使用者認為我不僅做了系統,還做了編譯器,還開發了一個類庫。做了那麼多事,回報是應該的。其實他們不知道,類庫是編寫作業系統所必須的,編譯器也是必須的,這些必須的東西卻可以在作業系統之外獲得更多的回報,真是太完美了!這是什嗎?這就是商業精神!當然這些誤解對我是有好處的,我就不必到處宣揚真相了。反正我把類庫的源碼都發布了,也沒有騙過人吧。我不過是在那個原始類庫中加進了一些與我的作業系統相關的東西,以方便在我的系統上編寫程式的人們,這是我的好心吧;至於有人可能產生進一步的誤解,就不是我需要考慮的了……
所以還是看看CRT的源碼吧——看看那些針對硬體平台的彙編;看看VC的標準C++庫和CRT關係;再看看其他動作系統的原始碼,想想CRT中的哪些部分可以支援用來寫作業系統,而如果我自己寫系統,又需要哪些東西;甚至你可以看看DOS的原始碼,想想和CRT的相似性,以及曆史淵源。可惜不能看到Windows的原始碼,否則一切就清楚了。
最後再說一句,C++當然不是Microsoft的專利。但是Microsoft選擇了C++,並取得了成功,這是肯定的了:象CRT,象VC,象Windows,象Office,象 SQLServer......這一方面說明了C++的優勢,一方面也是Microsoft自身的因素在起作用。然後,它當然要緊抓C++的大旗,大力宣揚它自己的C++,並排斥其他的C++。這就是帝國的“風範”了。所以對Microsoft,總是即恨且愛,總希望哪天它會良心發現——當然這隻是幻想罷了。不過,肯定該肯定的,否定該否定的,總是應該的。但就產品而言,Microsoft不是最好的,但大多都是最成功的,在看到它的不足的同時,也要看到它的優點。存在的即使不是合理的,也一定有它的合理性。所以,不能簡單用一兩句話評價Microsoft及它的成功。惟有一點是可以肯定的,它決定選擇C ++,真是太英明了!
-------------------------------------------
C Runtime Library
對於上面的這個太頭困惑了很久,現在轉貼一張
抄來的 共同學習哈
***************************************
1)執行階段程式庫就是 C run-time library,是 C 而非 C++ 語言世界的概念:取這個名字就是因為你的 C 程式運行時需要這些庫中的函數.
2)C 語言是所謂的“小核心”語言,就其語言本身來說很小(不多的關鍵字,程式流程式控制制,資料類型等);所以,C 語言核心開發出來之後, Dennis Ritchie 和 Brian Kernighan 就用 C 本身重寫了 90% 以上的 UNIX 系統函數,並且把其中最常用的部分獨立出來,形成標頭檔和對應的 LIBRARY,C run-time library 就是這樣形成的。
3)隨後,隨著 C 語言的流行,各個 C 編譯器的生產商/個體/團體都遵循老的傳統,在不同平台上都有相對應的 Standard Library,但大部分實現都是與各個平台有關的。由於各個 C 編譯器對 C 的支援和理解有很多分歧和微妙的差別,所以就有了 ANSI C;ANSI C (主觀意圖上)詳細的規定了 C 語言各個要素的具體含義和編譯器實現要求,引進了新的函式宣告方式,同時訂立了 Standard Library 的標準形式。所以C執行階段程式庫由編譯器生產商提供。至於由其他廠商/個人/團體提供的標頭檔和庫函數,應當稱為第三方 C 運行庫(Third party C run-time libraries)。
4)C run-time library裡面含有初始化代碼,還有錯誤處理代碼(例如divide by zero處理)。你寫的程式可以沒有 math庫,程式照樣運行,只是不能處理複雜的數學運算,不過如果沒有了C run-time庫,main()就不會被調用,exit()也不能被響應。因為C run-time library包含了C程式啟動並執行最基本和最常用的函數。
5)到了 C++ 世界裡,有另外一個概念:Standard C++ Library,它包括了上面所說的 C run- time library 和 STL。包含 C run-time library 的原因很明顯,C++ 是 C 的超集,沒有理由再重新來一個 C ++ run-time library. VC針對C++ 加入的Standard C++ Library主要包括:LIBCP.LIB, LIBCPMT.LIB和 MSVCPRT.LIB
6)Windows環境下,VC提供的 C run-time library又分為動態執行階段程式庫和靜態執行階段程式庫。
動態執行階段程式庫主要是DLL庫檔案msvcrt.dll(or MSVCRTD.DLL for debug build),對應的Import library檔案是MSVCRT.LIB(MSVCRTD.LIB for debug build)
靜態執行階段程式庫(release版)對應的主要檔案是:
LIBC.LIB (Single thread static library, retail version)
LIBCMT.LIB (Multithread static library, retail version)
msvcrt.dll提供幾千個C函數,即使是像printf這麼低級的函數都在msvcrt.dll裡。其實你的程式運行時,很大一部分時間時在這些運行庫裡運行。在你的程式(release版)被編譯時間,VC會根據你的編譯選項(單線程、多線程或DLL)自動將相應的執行階段程式庫檔案 (libc.lib,libcmt.lib或Import library msvcrt.lib)連結進來。
編譯時間到底哪個C run-time library聯入你的程式取決於編譯選項:
/MD, /ML, /MT, /LD (Use Run-Time Library)
你可以VC中通過以下方法設定選擇哪個C run-time library聯入你的程式:
To find these options in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Code Generation in the Category box. See the Use Run-Time Library drop-down box.
從程式可移植性考慮,如果兩函數都可完成一種功能,選執行階段程式庫函數好,因為各個 C 編譯器的生產商對標準C Run-time library提供了統一的支援.