第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

編譯/鏈接過程是如何工作的?

編譯/鏈接過程是如何工作的?

C C++
繁花如伊 2019-05-30 17:20:24
編譯/鏈接過程是如何工作的?編譯和鏈接過程是如何工作的?(注:這是指堆棧溢出的C+常見問題。如果您想批評以這種形式提供常見問題的想法,那么在元網(wǎng)站上發(fā)布的文章引發(fā)了這一切就是這樣做的地方。對該問題的回答將在C+聊天室你的答案很可能會被那些想出這個想法的人讀懂。)
查看完整描述

4 回答

?
烙印99

TA貢獻1829條經(jīng)驗 獲得超13個贊

C+程序的編譯包括三個步驟:

  1. 預(yù)處理:預(yù)處理程序采用C+源代碼文件,并處理#includeS,#defineS和其他預(yù)處理指令。這個步驟的輸出是一個“純”C+文件,沒有預(yù)處理指令。

  2. 編譯:編譯器獲取預(yù)處理器的輸出并從中生成一個對象文件.

  3. 鏈接:鏈接器獲取編譯器生成的對象文件,并生成庫或可執(zhí)行文件。

預(yù)處理

預(yù)處理程序處理預(yù)處理指令,就像#include#define。它不知道C+的語法,這就是為什么必須謹(jǐn)慎使用它的原因。

它一次工作在一個C+源文件上,方法是#include具有相應(yīng)文件內(nèi)容的指令(通常只是聲明),替換宏(#define),并根據(jù)以下內(nèi)容選擇文本的不同部分:#if#ifdef#ifndef指令。

預(yù)處理器工作在預(yù)處理令牌流上。宏替換定義為用其他令牌替換令牌(操作符)。##當(dāng)有意義時,啟用合并兩個令牌)。

在所有這些之后,預(yù)處理器產(chǎn)生一個單一的輸出,這是由上面描述的轉(zhuǎn)換產(chǎn)生的令牌流。它還添加了一些特殊的標(biāo)記,告訴編譯器每一行來自哪里,這樣它就可以使用這些標(biāo)記來生成合理的錯誤消息。

在此階段,可以通過巧妙地使用#if#error指令。

編撰

編譯步驟對預(yù)處理程序的每個輸出執(zhí)行。編譯器解析純C+源代碼(現(xiàn)在沒有任何預(yù)處理器指令)并將其轉(zhuǎn)換為程序集代碼。然后調(diào)用底層后端(工具鏈中的匯編程序),將該代碼組裝成生成某種格式的實際二進制文件的機器代碼(ELF,COFF,a.out,.)。此對象文件包含輸入中定義的符號的編譯代碼(二進制形式)。對象文件中的符號按名稱引用。

對象文件可以引用未定義的符號。如果使用聲明,而不提供聲明的定義,則會出現(xiàn)這種情況。編譯器不介意這一點,只要源代碼格式良好,編譯器就會很高興地生成對象文件。

編譯器通常允許您在此時停止編譯。這非常有用,因為使用它,您可以分別編譯每個源代碼文件。它提供的優(yōu)點是您不需要重新編譯一切如果您只更改一個文件。

生成的對象文件可以放在稱為靜態(tài)庫的特殊檔案中,以便以后更容易重用。

在這個階段,報告了“常規(guī)”編譯器錯誤,比如語法錯誤或失敗的過載解析錯誤。

鏈接

鏈接器是編譯器生成的對象文件的最終編譯輸出。這個輸出可以是一個共享的(或者是動態(tài)的)庫(雖然名稱相似,但它們與前面提到的靜態(tài)庫沒有多少共同點),也可以是一個可執(zhí)行文件。

它通過用正確的地址替換對未定義符號的引用來鏈接所有對象文件。這些符號中的每一個都可以在其他對象文件或庫中定義。如果它們是在標(biāo)準(zhǔn)庫以外的庫中定義的,則需要將它們告知鏈接器。

在這個階段,最常見的錯誤是缺少定義或重復(fù)定義。前者意味著定義不存在(即它們不被寫入),或者它們所在的對象文件或庫沒有提供給鏈接器。后者是顯而易見的:在兩個不同的對象文件或庫中定義了相同的符號。


查看完整回答
反對 回復(fù) 2019-05-30
?
慕雪6442864

TA貢獻1812條經(jīng)驗 獲得超5個贊

精簡是指CPU從內(nèi)存地址加載數(shù)據(jù),將數(shù)據(jù)存儲到內(nèi)存地址,然后從內(nèi)存地址順序執(zhí)行指令,在處理的指令序列中有一些條件跳轉(zhuǎn)。這三種指令中的每一種都涉及到計算要在機器指令中使用的存儲器單元的地址。由于機器指令的長度取決于所涉及的特定指令,而且由于我們在構(gòu)建機器代碼時將其中的可變長度串在一起,所以在計算和構(gòu)建任何地址時需要兩個步驟。

首先,我們盡可能地安排內(nèi)存分配,然后才能知道每個單元的確切情況。我們計算出字節(jié),或單詞,或構(gòu)成指令、文字和任何數(shù)據(jù)的任何東西。我們只是開始分配內(nèi)存和構(gòu)建值,這些值將在我們運行時創(chuàng)建程序,并記下我們需要返回并修復(fù)地址的任何地方。在那個地方,我們放置一個假人來填充位置,這樣我們就可以繼續(xù)計算內(nèi)存大小。例如,我們的第一個機器代碼可能需要一個單元格。下一個機器代碼可能包含3個單元,包括一個機器代碼單元和兩個地址單元?,F(xiàn)在我們的地址指針是4。我們知道機器單元是什么,這是OP代碼,但是我們必須等待計算地址單元格中的內(nèi)容,直到我們知道數(shù)據(jù)的位置,即數(shù)據(jù)的機器地址是什么。

如果只有一個源文件,理論上編譯器可以在沒有鏈接器的情況下生成完全可執(zhí)行的機器代碼。在兩次傳遞過程中,它可以計算出任何機器加載或存儲指令所引用的所有數(shù)據(jù)單元的所有實際地址。它可以計算任何絕對跳轉(zhuǎn)指令所引用的所有絕對地址。這是一個簡單的編譯器,就像Forth Work中的編譯器,沒有鏈接器。

鏈接器允許單獨編譯代碼塊。這可以加快構(gòu)建代碼的整個過程,并允許在以后如何使用這些塊時具有一定的靈活性,換句話說,它們可以在內(nèi)存中重新定位,例如在每個地址中添加1000個地址,以使塊增加1000個地址單元格。

所以編譯器輸出的是尚未完全構(gòu)建的粗略的機器代碼,而是布局好的,這樣我們就知道了所有東西的大小,換句話說,我們就可以開始計算所有絕對地址的位置。編譯器還輸出一個符號列表,這些符號是名稱/地址對。符號將模塊中機器代碼中的內(nèi)存偏移量與名稱相關(guān)聯(lián)。偏移量是到模塊中符號的存儲器位置的絕對距離。

那就是我們找到鏈接器的地方。鏈接器首先將所有這些機器代碼塊連接到一起,并記下每個代碼的起始位置。然后,通過將模塊內(nèi)部的相對偏移量和模塊在較大布局中的絕對位置相加,計算要固定的地址。

顯然,我過于簡化了這一點,所以您可以嘗試?yán)斫馑?,而且我故意不使用對象文件、符號表等術(shù)語。這對我來說是混亂的一部分。


查看完整回答
反對 回復(fù) 2019-05-30
  • 4 回答
  • 0 關(guān)注
  • 805 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號