crt是什么意思 windows编程_从零开始,学习windows编程 - hello.c的疑惑!
我們現(xiàn)在有的,是一個hello.c文件,通過cl命令就可以生成目標hello.exe文件。
那我們就可以研究一下cl這個東西。
CL解釋
CL.EXE(或cl.exe,似乎windows的文件系統(tǒng)對于大小寫是不敏感的),是何許人也呢?
因為VC6的版本說明沒有找到,這里的說明文字是Visual studio 2013的CL.EXE說明,不過都是一樣的。
CL是用來控制微軟C和C++編譯器(compiler)和鏈接器(linker),一共做了兩件事情。編譯器會生成COFF文件格式的目標文件(.obj);鏈接器會生成可執(zhí)行文件(.exe)或者動態(tài)鏈接庫文件(DLLs)。
對比我們之前的做法,的確是執(zhí)行cl命令之后,生成了一個hello.obj文件和一個hello.exe文件。
選項的使用
數(shù)了一下,有99個選項之多。每個選項都有自己的作用,就需要使用的時候去熟悉了,不過我們現(xiàn)在不需要了解這么多,我們就來看下/c選項好了。This option prevents the automatic call to LINK. Compiling with /c creates .obj files only. You must call LINK explicitly with the proper files and options to perform the linking phase of the build.
Any internal project created in the development environment uses the /c option by default.
To set this compiler option in the Visual Studio development environment
This option is not available from within the development environment.
To set this compiler option programmatically
This compiler option cannot be changed programmatically.
要徹底理解它,就必須知道C語言到目標代碼的過程。
▓首先,C語言中有兩種文件,一個.c文件(我們一般稱之為源文件),一個.h文件(我們一般稱之為頭文件)。頭文件一般會被源文件包含,而源文件會被編譯成一個二進制中間文件,之后所有的二進制中間文件會通過鏈接器進行鏈接,形成一個可以在某個特定系統(tǒng)上執(zhí)行的二進制可執(zhí)行文件。
于是,C語言-->可執(zhí)行代碼可以明顯的分為編譯過程和鏈接過程,而由于C語言中一種特殊語法--“宏”的存在,所以還有一個預編譯過程,在預編譯過程中,C語言中的宏會被展開;同時,包含的頭文件中的代碼,會根據(jù)條件編譯等,囊括到源文件中,這些工作做好后,給編譯器的就是一份新的源碼文件,供編譯階段使用。
另外,相信大家都知道,C語言是從匯編語言發(fā)展過來的,匯編是從機器碼發(fā)展過來的,以前的編譯器都是先將C語言編譯成匯編語言,再將其解釋成機器碼就可以了。現(xiàn)代編譯器除了做這個,還可以對代碼進行優(yōu)化。不過基本思想是一直沒有變的。
而我們做C開發(fā)的時候,有時稍微看一下匯編之后的代碼,對于計算機是如何執(zhí)行程序的過程,會有更清晰的認識。
那么,用cl可以生成匯編代碼嗎?答案當然是肯定的。
在命令行輸入cl /FA hello.c,看看生成了哪些東西?當然,如果你不要生成.exe文件,可以加上/c選項。
可以看到生成了.obj文件和.asm文件。
.asm的匯編代碼,僅僅用cl再進行編譯,我還沒有找到方法,所以這里就要引入一個新工具--ml,ml是MASM中編譯匯編代碼使用的編譯器,同樣,它也會調(diào)用到link,并且讓它不調(diào)用link,使用的編譯選項也是/c。
從cl和hello.c,我們引出了hello.obj,hello.asm,以及ml.exe,包括C語言到可執(zhí)行文件的過程。下面先跳過ml,來看看鏈接過程。
鏈接過程
鏈接過程也就是將.obj變成.exe的過程,使用的是link.exe。
直接使用cl /c hello.c產(chǎn)生的hello.obj文件,輸入命令link hello.obj,直接就生成了.exe文件。
真簡單~不過,且慢,我們有main函數(shù),但是至少printf函數(shù)這個東西,是在哪里呢?
秘密就藏在生成的那個.obj文件中啦!如果用另外一個.obj文件(稍候我們會用另外一個hello.obj),那就會得到錯誤哦。
那我們打開obj文件來看看吧。怎么?還要看二進制文件?不用擔心,看的還是英文字符,多說無用,還是看下就知道了。
這里我使用的是winhex,其實使用其他任何一個文本編輯器都是可以的,不過看二進制文件我還是習慣使用專門的二進制編輯器。截圖用的picpick。順便說明下。
左邊是文件內(nèi)容,主要看右邊,紅線劃過的地方。看不清的同學可以看這里:-defaultlib:LIBC –defaultlib:OLDNAMES
其實,鏈接過程會將所有的靜態(tài)庫和目標文件進行鏈接,而在這份hello.obj文件中,指定了兩個default lib,一個為libc.lib,一個為oldnames.lib。而這兩個lib文件又是何方神圣呢?
libc.lib為單線程靜態(tài)C標準庫(在cl中可使用/ML選項定義對其的鏈接),而oldnames.lib則是為了兼容微軟以前的C/C++開發(fā)系統(tǒng),基本不使用了,至少在我們這個hello.c編譯鏈接成exe的過程中,可以忽略掉它。
其實,我們用一個很簡單的方法可以知道我們的程序鏈接了哪些庫。d:\test>link?/verbose:lib?hello.obj
Microsoft?(R)?Incremental Linker Version?6.00.8168
Copyright?(C)?Microsoft Corp?1992-1998.?All rights reserved.
Searching Libraries
Searching D:\Program?Files\Microsoft Visual Studio\VC98\lib\LIBC.lib:
Searching D:\Program?Files\Microsoft Visual Studio\VC98\lib\OLDNAMES.lib:
Searching D:\Program?Files\Microsoft Platform SDK\Lib\.\kernel32.lib:
Done Searching Libraries
這里還可以使用一個小工具,叫做dumpbin的,可以利用它的選項來分析hello.obj文件,看到defaultlib,而不用打開文件自己查看。
——————————————
d:\test>dumpbin?/DIRECTIVES hello.obj
Microsoft (R) COFF Binary File Dumper Version?6.00.81683?Copyright (C) Microsoft Corp?1992-1998. All rights reserved.
Dump of file hello.obj
File Type: COFF OBJECT
Linker Directives
-----------------
-defaultlib:LIBC
-defaultlib:OLDNAMES
Summary
A .data
26?.drectve
14?.text
——————————
oldnames.lib我們可以略過,但是libc.lib我們還是需要了解的,今后要做VC相關項目,使用到第三方庫的會經(jīng)常用到。為了解釋libc.lib,我們需要引入一個新的概念--“C語言運行庫”,這里我們只討論windows平臺,VC中使用的被稱為MSVC CRT。
另外還要牽涉到的一個概念就是線程。
C語言運行時庫(C Run-time Library)---CRT
要了解這個東西,就需要對C語言的發(fā)展史有一定的了解。C語言是在上世紀70年代在B語言的基礎上被發(fā)明出來的,之后Dennis Ritchie 和 Brian Kernighan 就用C本身重寫了90%以上的 UNIX 系統(tǒng)函數(shù)。并且把其中最常用的部分獨立出來,形成頭文件和對應的 LIBRARY,C run-time library 就是這樣形成的。在類UNIX系統(tǒng)中,C運行庫被認為是系統(tǒng)的一部分。
而隨著C語言的流行,出現(xiàn)了很多C編譯器,也就有很多C運行時庫的實現(xiàn)。主要有下面的幾種
BSD libc, implementations distributed under?BSD?operating systems.
?GNU C Library, used in?GNU/Linux?and?GNU/HURD.
?Dinkum C99 Library from?Dinkumware, most common commercially licensed one
?Microsoft C Run-time Library, part of?Microsoft Visual C++
?dietlibc, an alternative small implementation of the C standard library (MMU-less)
?uClibc, a C standard library for embedded?Linux?systems (MMU-less)
?Newlib, a C standard library for embedded systems (MMU-less)
?klibc, primarily for booting Linux systems.
?EGLIBC, variant of glibc for embedded systems.
?musl, another lightweight C standard library implementation for Linux systems
可以看到,我們現(xiàn)在討論的Microsoft C Run-time Library也是其中的一種。在那個年代,線程還沒有被應用到操作系統(tǒng)上,應用程序都是單線程的。所以最初的C Run-time Library都是單線程的。另外動態(tài)庫的概念也是后期出現(xiàn)的,所以一開始C Run-time Library也只是靜態(tài)鏈接。
隨著時間的推移,計算機技術也在不斷進步。C語言運行時庫也根據(jù)單線程、多線程、靜態(tài)鏈接、動態(tài)鏈接,是否需要debug信息的不同,分為不同的版本。在微軟是MSVC CRT實現(xiàn)中,具體是按照表格中的實現(xiàn)來分類的。其中,靜態(tài)鏈接有單線程和多線程版本,動態(tài)鏈接僅有多線程版本。
使用link鏈接CRT
前面我們的obj文件中就包含有default lib,那如果我們的obj文件中不包含該信息呢?
首先,我們需要生成一個不包含default lib信息的obj文件。
這里有兩種方法,一種是生成ASM文件,然后利用ml來生成一個obj文件,其中不包含該信息(當然ml也會主動調(diào)用link,這里也需要使用選項來控制,具體有興趣的童鞋可以自行研究,因為這里主要還是C/C++編程為主,匯編會涉及,但是不會深入);還有一種方法是利用cl的/Zl選項,這里要注意的是l是小寫的L而不是I,我一開始就是看錯了,結果編譯出來還是帶有default lib信息的。cl?/c?/Zl hello.c
之后利用dumpbin來查看一下是否生成正確。然后再調(diào)用link看看。
結果如下:
現(xiàn)在就找不到_printf和_mainCRTStartup這兩個符號了。
之后使用link hello.obj libc.lib看看。
成功生成hello.exe!
總結
使用到的工具
★CL.EXE
★LINK.EXE
★ML.EXE
★DUMPBIN.EXE
★WINHEX
整個C程序編譯過程, MSVC和GCC對比
VC文件后綴名
“我是一名從事了10年開發(fā)在退休邊緣垂死掙扎的高齡程序員,最近我花了一些時間整理了一個完整的學習C語言、C++的路線,項目源碼和工具?C/C++編程項目開發(fā)學習視頻,素材筆記,項目源碼等,還有新鮮出爐的學生成績管理系統(tǒng)?~ 對于想學習C/C++的小伙伴而言,學習的氛圍和志同道合的伙伴很重要,筆者強烈推薦主頁的編程愛好者的聚集地!
歡迎初學和進階中的小伙伴。希望你也能憑自己的努力,成為下一個優(yōu)秀的程序員。工作需要、感興趣、為了入行、轉(zhuǎn)行需要學習C/C++的伙伴可以一起學習!”
關注我,帶你遨游代碼世界!
下面這些是C/C++能做的 :
服務器開發(fā)工程師、人工智能、云計算工程師、信息安全(白客)、大數(shù)據(jù) 、數(shù)據(jù)平臺、嵌入式工程師、流媒體服務器、數(shù)據(jù)控解、圖像處理、音頻視頻開發(fā)工程師、游戲服務器、分布式系統(tǒng)、游戲輔助等!
總結
以上是生活随笔為你收集整理的crt是什么意思 windows编程_从零开始,学习windows编程 - hello.c的疑惑!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【工具】switchhost
- 下一篇: Taro+react开发(80):状态改