C 編譯過程

2021-09-26 23:43:08 字數 1297 閱讀 5545

很多人只知道c# 應用程式執行 必須有clr(公共語言執行時)和.net框架的支援,但不知道為啥需要?

其實很簡單,因為.exe只是il指令,cil(公共中間語言),目前的cpu還不能直接執行il指令,但將來的cpu也許會具有這種能力。執行exe它的il**還必須首先被轉換成為本地cpu指令,這屬於clr中即時編譯器的工作。總所周知,程式入口點是main函式,在程式執行之前,clr檢測main中**所引用到的所有型別,分配多個內部的資料結構,乙個類對應乙個資料結構,類中每個方法都會有乙個對應的條目,每個條目儲存有乙個方法實現**的位址。

當main函式第一次呼叫程式中的某個方法時,jitcompiler函式將被呼叫,也就是將該方法的il**編譯成本地的cpu指令,注意這是即時編譯的,這些本地cpu指令將被儲存在乙個動態分配的記憶體塊中,然後jitcompiler將前面內部資料結構中被呼叫方法的位址替換為包含本地cpu指令的記憶體塊位址。最後jitcompiler將跳轉到該記憶體塊的**上。這就是即時編譯所做的工作,當該方法執行完畢,它將返回到main函式中,繼續執行下面的**。

main函式第二次呼叫程式的某個方法時,該方法的il已經被編譯成cpu指令,所以這一次執行將直接呼叫記憶體塊中已有的本地**,也正因為如此,乙個方法只有在首次呼叫時才會產生一些效能上的損失。但所有對該方法的後續呼叫都將以本地**全速執行。

jit編譯器將本地**儲存於動態記憶體之中,這就意味著關閉程式時,編譯生成的本地**將會被丟棄。再次執行程式依舊要把il**轉換為cpu指令,這就是為什麼每次執行都需要clr及.net框架支援的原因。

c#語言執行時要經過兩次編譯,第一次編譯是將源**編譯為msil(微軟中間語言),即可以發布軟體了。當軟體執行時msil**載入記憶體時會進行第二次編譯,中間語言會編譯為機器語言以供計算機呼叫,第二次編譯只在載入記憶體時發生,編譯的結果被儲存起來以備重複利用。編譯時是按需編譯,即只編譯所用到的**,而不是全部程式,稱為jit(即時編譯)。

編譯過linux的朋友應該都熟悉make檔案吧,在這裡面可以清楚的看到使用編譯器把c源**編譯成二進位制源**的流程,中間幹了什麼都可以看得清清楚楚。但使用vs的朋友一般都是程式寫好之後直接f5就執行了,後面做了什麼我們根本不知道。對於cosmos的源**,vs只是幫我們編譯成了il的**,這種**無法在沒有clr環境中執行,所以vs還需要把il**編譯為針對cpu的本地**。這中間的流程都由msbuild這個東西控制。對於msbuild的介紹可以直接檢視msdn文件。總的來說這個東西的地位就相當於make檔案的地位吧,指導vs如何生成可以引導的二進位制檔案。

c編譯過程

編譯的概念 編譯程式讀取源程式 字元流 對之進行詞法和語法的分析,將高階語言指令轉換為功能等效的彙編 再由匯程式設計序轉換為機器語言,並且按照作業系統對可執行檔案格式的要求鏈結生成可執行程式。編譯的完整過程 c源程式 預編譯處理 c 編譯 優化程式 s asm 匯程式設計序 obj o a ko 鏈...

c 編譯過程

編譯過程主要分為 4個過程 1 編譯預處理 預編譯程式完成的工作,可以說成是對源程式的 替換 工作。經過這個過程,生成乙個沒有巨集定義 沒有條件編譯指令 沒有特殊符號的輸出檔案。2 編譯 優化階段 通過詞法分析 語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間 或彙編 在c 中,以...

C 編譯過程

以helloword.c 程式說明編譯過程 在預設的狀態下,如果我們直接以gcc編譯原始碼,並且沒有加上任何引數,則執行檔案的檔名會被自動設定為a.out 這個檔名。所以你就能夠直接執行 a.out這個這行檔案。hello.c 就是原始碼,gcc是編譯程式,a.out 是編譯成功的可執行檔案。如果我...