編譯原理什麼是規范句型
① 編譯原理
C語言編譯過程詳解
C語言的編譯鏈接過程是要把我們編寫的一個C程序(源代碼)轉換成可以在硬體上運行的程序(可執行代碼),需要進行編譯和鏈接。編譯就是把文本形式源代碼翻譯為機器語言形式的目標文件的過程。鏈接是把目標文件、操作系統的啟動代碼和用到的庫文件進行組織形成最終生成可執行代碼的過程。過程圖解如下:
從圖上可以看到,整個代碼的編譯過程分為編譯和鏈接兩個過程,編譯對應圖中的大括弧括起的部分,其餘則為鏈接過程。
一、編譯過程
編譯過程又可以分成兩個階段:編譯和匯編。
1、編譯
編譯是讀取源程序(字元流),對之進行詞法和語法的分析,將高級語言指令轉換為功能等效的匯編代碼,源文件的編譯過程包含兩個主要階段:
第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在文件中的預處理指令來修改源文件的內容。如#include指令就是一個預處理指令,它把頭文件的內容添加到.cpp文件中。這個在編譯之前修改源文件的方式提供了很大的靈活性,以適應不同的計算機和操作系統環境的限制。一個環境需要的代碼跟另一個環境所需的代碼可能有所不同,因為可用的硬體或操作系統是不同的。在許多情況下,可以把用於不同環境的代碼放在同一個文件中,再在預處理階段修改代碼,使之適應當前的環境。
主要是以下幾方面的處理:
(1)宏定義指令,如 #define a b。
對於這種偽指令,預編譯所要做的是將程序中的所有a用b替換,但作為字元串常量的 a則不被替換。還有 #undef,則將取消對某個宏的定義,使以後該串的出現不再被替換。
(2)條件編譯指令,如#ifdef,#ifndef,#else,#elif,#endif等。
這些偽指令的引入使得程序員可以通過定義不同的宏來決定編譯程序對哪些代碼進行處理。預編譯程序將根據有關的文件,將那些不必要的代碼過濾掉
(3) 頭文件包含指令,如#include "FileName"或者#include <FileName>等。
在頭文件中一般用偽指令#define定義了大量的宏(最常見的是字元常量),同時包含有各種外部符號的聲明。採用頭文件的目的主要是為了使某些定義可以供多個不同的C源程序使用。因為在需要用到這些定義的C源程序中,只需加上一條#include語句即可,而不必再在此文件中將這些定義重復一遍。預編譯程序將把頭文件中的定義統統都加入到它所產生的輸出文件中,以供編譯程序對之進行處理。包含到C源程序中的頭文件可以是系統提供的,這些頭文件一般被放在/usr/include目錄下。在程序中#include它們要使用尖括弧(<>)。另外開發人員也可以定義自己的頭文件,這些文件一般與C源程序放在同一目錄下,此時在#include中要用雙引號("")。
(4)特殊符號,預編譯程序可以識別一些特殊的符號。
例如在源程序中出現的LINE標識將被解釋為當前行號(十進制數),FILE則被解釋為當前被編譯的C源程序的名稱。預編譯程序對於在源程序中出現的這些串將用合適的值進行替換。
預編譯程序所完成的基本上是對源程序的「替代」工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機器指令。
第二個階段編譯、優化階段。經過預編譯得到的輸出文件中,只有常量;如數字、字元串、變數的定義,以及C語言的關鍵字,如main,if,else,for,while,{,}, +,-,*,\等等。
編譯程序所要作得工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間代碼表示或匯編代碼。
優化處理是編譯系統中一項比較艱深的技術。它涉及到的問題不僅同編譯技術本身有關,而且同機器的硬體環境也有很大的關系。優化一部分是對中間代碼的優化。這種優化不依賴於具體的計算機。另一種優化則主要針對目標代碼的生成而進行的。
對於前一種優化,主要的工作是刪除公共表達式、循環優化(代碼外提、強度削弱、變換循環控制條件、已知量的合並等)、復寫傳播,以及無用賦值的刪除,等等。
後一種類型的優化同機器的硬體結構密切相關,最主要的是考慮是如何充分利用機器的各個硬體寄存器存放的有關變數的值,以減少對於內存的訪問次數。另外,如何根據機器硬體執行指令的特點(如流水線、RISC、CISC、VLIW等)而對指令進行一些調整使目標代碼比較短,執行的效率比較高,也是一個重要的研究課題。
2、匯編
匯編實際上指把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。目標文件由段組成。通常一個目標文件中至少有兩個段:
代碼段:該段中所包含的主要是程序的指令。該段一般是可讀和可執行的,但一般卻不可寫。
數據段:主要存放程序中要用到的各種全局變數或靜態的數據。一般數據段都是可讀,可寫,可執行的。
UNIX環境下主要有三種類型的目標文件:
(1)可重定位文件
其中包含有適合於其它目標文件鏈接來創建一個可執行的或者共享的目標文件的代碼和數據。
(2)共享的目標文件
這種文件存放了適合於在兩種上下文里鏈接的代碼和數據。
第一種是鏈接程序可把它與其它可重定位文件及共享的目標文件一起處理來創建另一個 目標文件;
第二種是動態鏈接程序將它與另一個可執行文件及其它的共享目標文件結合到一起,創建一個進程映象。
(3)可執行文件
它包含了一個可以被操作系統創建一個進程來執行之的文件。匯編程序生成的實際上是第一種類型的目標文件。對於後兩種還需要其他的一些處理方能得到,這個就是鏈接程序的工作了。
二、鏈接過程
由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。
例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變數或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。
鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來,使得所有的這些目標文件成為一個能夠被操作系統裝入執行的統一整體。
根據開發人員指定的同庫函數的鏈接方式的不同,鏈接處理可分為兩種:
(1)靜態鏈接
在這種鏈接方式下,函數的代碼將從其所在地靜態鏈接庫中被拷貝到最終的可執行程序中。這樣該程序在被執行時這些代碼將被裝入到該進程的虛擬地址空間中。靜態鏈接庫實際上是一個目標文件的集合,其中的每個文件含有庫中的一個或者一組相關函數的代碼。
(2) 動態鏈接
在此種方式下,函數的代碼被放到稱作是動態鏈接庫或共享對象的某個目標文件中。鏈接程序此時所作的只是在最終的可執行程序中記錄下共享對象的名字以及其它少量的登記信息。在此可執行文件被執行時,動態鏈接庫的全部內容將被映射到運行時相應進程的虛地址空間。動態鏈接程序將根據可執行程序中記錄的信息找到相應的函數代碼。
對於可執行文件中的函數調用,可分別採用動態鏈接或靜態鏈接的方法。使用動態鏈接能夠使最終的可執行文件比較短小,並且當共享對象被多個進程使用時能節約一些內存,因為在內存中只需要保存一份此共享對象的代碼。但並不是使用動態鏈接就一定比使用靜態鏈接要優越。在某些情況下動態鏈接可能帶來一些性能上損害。
我們在linux使用的gcc編譯器便是把以上的幾個過程進行捆綁,使用戶只使用一次命令就把編譯工作完成,這的確方便了編譯工作,但對於初學者了解編譯過程就很不利了,下圖便是gcc代理的編譯過程:
從上圖可以看到:
預編譯
將.c 文件轉化成 .i文件
使用的gcc命令是:gcc –E
對應於預處理命令cpp
編譯
將.c/.h文件轉換成.s文件
使用的gcc命令是:gcc –S
對應於編譯命令 cc –S
匯編
將.s 文件轉化成 .o文件
使用的gcc 命令是:gcc –c
對應於匯編命令是 as
鏈接
將.o文件轉化成可執行程序
使用的gcc 命令是: gcc
對應於鏈接命令是 ld
總結起來編譯過程就上面的四個過程:預編譯、編譯、匯編、鏈接。了解這四個過程中所做的工作,對我們理解頭文件、庫等的工作過程是有幫助的,而且清楚的了解編譯鏈接過程還對我們在編程時定位錯誤,以及編程時盡量調動編譯器的檢測錯誤會有很大的幫助的。
② 什麼是(文法的)規范推導(編譯原理))
規范推導:最右推導
最右推導、最左推導、規范推導、規范句型
對於文法:G[S]:S → aAS | a
A → SbA | SS | ba
最右推導:S=> aA S =>a A a=>aSb A a
=>a S bbaa=>aabbaa(每次只推導 最右邊 的非終結符,直到推導完畢)
(得到的句型為 規范句型 )
最左推導: S=>a A S=>a S bAS=>aab A S
=>aabba S =>aabbaa(與最右推導類比理解)
③ 編譯原理-句型、句子、短語、直接短語、句柄、素短語、最左素短語
在進行語法分析的時候,有時候會對這些詞語的概念不清晰,這里我們就詳細歸納總結一下。
可以看出這個裡面,最需要理解的概念就是短語,其他大部分概念都是在短語基礎上延伸的,從概念上可以看出:
假設有一個文法
針對文法的一個特定句型 (Sd(T)db) , 其推導過程如下:
這個句型 (Sd(T)db) 對應的 CFG 分析樹如下:
那個這個句型 (Sd(T)db) 有多少個短語呢?
還記得短語的定義么, S ⇒* αβδ , αβδ 代表句型就是這里的 (Sd(T)db) 。
因此這個句型 (Sd(T)db) :
演算法非常簡單,就是通過分析樹的後序遍歷,先將子樹的葉節點從左到右排合並成字元串(即一個短語),然後用它代表子樹的根節點的值,再和與子樹根節點同一層節點值合並,得到新的短語。就這樣從分析樹的最底層,一路合並到分析樹的根節點,就能得到所有的短語了。
通過遞歸的方法,獲取短語列表 phraseList , 直接短語列表 directPhraseList 和 素短語列表 plainPhraseList 。
運行結果:
④ 在編譯原理中,語法規則和詞法規則有什麼不同..
通俗的說,
規則主要識別單詞
語法主要識別多個單片語成的句子
⑤ 規約的編譯原理
推導的逆過程稱為規約。規約就是選擇一個文法規則:X→ABC,依次從棧頂彈出C、B、A,再將X壓進棧。規范規約是文法中句子的一個最右推導的逆過程,而最左推導對應的是最右規約 。
另外在程序設計中的規約:∏和∏'是兩個判定性問題,如果存在一個確定性演算法A使得對於一個∏的實例I,A可以將I在多項式時間里轉換成∏'的實例P,使得I得到肯定的回答,當且僅當I'得到肯定回答,則稱∏在多項式時間里規約到∏',記為∏∝poly∏'.
⑥ 請問規范規約是什麼意思(這個詞應該是用在計算機編譯原理中)
在編譯原理中,規范規約是編譯程序中語法分析(自下而上分析)階段的,在此階段中處理文法和句子。規范規約是文法中句子的一個最右推導的逆過程。
如果你是沒學過編譯原理的,這個具體要說意思的話,太抽象。你只要知道編譯程序的工作是從輸入源程序開始到輸出目標程序為止的整個過程,而這個過程可分為五個階段:詞法分析、語法分析、語義分析與中間代碼產生、優化、目標代碼生成。規范規約就是語法分析中用到的,為後面的步驟做准備。
⑦ 有關編譯原理
⑴拓廣文法 1 分
G[S ′ ]: S ′→ S ⑴
S → SaA ⑵ S → a ⑶ A → AbS ⑷ A → b ⑸
該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA :
⑵ 該文法的 LR(0) 分析表:
狀態 ACTION GOTO
a b # S A
0 S 2 1
1 S 3 acc
2 r 3 r 3 r 3
3 S 5 4
4 r 2 r 2 /S 6 r 2
5 r 5 r 5 r 5
6 S 2 7
7 r 4 /S 3 r 4 r 4
⑶ LR(0) 文法:該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA 中沒有沖突狀態。
該文法不是 LR(0) 文法
因為存在沖突狀態: I 4 和 I 7
⑷ SLR(1) 文法:該文法的以 LR(0) 項目集為狀態的識別規范句型活前綴的 DFA 中有沖突狀態,沖突可用 FOLLOW 集解決。
該文法不是 SLR(1) 文法。
因為 FOLLOW(S)={a,b,#} ,所以無法解決沖突
⑧ 【編譯原理】第二章:語言和文法
上述文法 表示,該文法由終結符集合 ,非終結符集合 ,產生式集合 ,以及開始符號 構成。
而產生式 表示,一個表達式(Expression) ,可以由一個標識符(Identifier) 、或者兩個表達式由加號 或乘號 連接、或者另一個表達式用括弧包裹( )構成。
約定 :在不引起歧義的情況下,可以只寫產生式。如以上文法可以簡寫為:
產生式
可以簡寫為:
如上例中,
可以簡寫為:
給定文法 ,如果有 ,那麼可以將符號串 重寫 為 ,記作 ,這個過程稱為 推導 。
如上例中, 可以推導出 或 或 等等。
如果 ,
可以記作 ,則稱為 經過n步推導出 ,記作 。
推導的反過程稱為 歸約 。
如果 ,則稱 是 的一個 句型(sentential form )。
由文法 的開始符號 推導出的所有句子構成的集合稱為 文法G生成的語言 ,記作 。
即:
例
文法
表示什麼呢?
代表小寫字母;
代表數字;
表示若干個字母和數字構成的字元串;
說明 是一個字母、或者是字母開頭的字元串。
那麼這個文法表示的即是,以字母開頭的、非空的字元串,即標識符的構成方式。
並、連接、冪、克林閉包、正閉包。
如上例表示為:
中必須包含一個 非終結符 。
產生式一般形式:
即上式中只有當上下文滿足 與 時,才能進行從 到 的推導。
上下文有關文法不包含空產生式( )。
產生式的一般形式:
即產生式左邊都是非終結符。
右線性文法 :
左線性文法 :
以上都成為正則文法。
即產生式的右側只能有一個終結符,且所有終結符只能在同一側。
例:(右線性文法)
以上文法滿足右線性文法。
以上文法生成一個以字母開頭的字母數字串(標識符)。
以上文法等價於 上下文無關文法 :
正則文法能描述程序設計語言中的多數單詞。
正則文法能描述程序設計語言中的多數單詞,但不能表示句子構造,所以用到最多的是CFG。
根節點 表示文法開始符號S;
內部節點 表示對產生式 的應用;該節點的標號是產生式左部,子節點從左到右表示了產生式的右部;
葉節點 (又稱邊緣)既可以是非終結符也可以是終結符。
給定一個句型,其分析樹的每一棵子樹的邊緣稱為該句型的一個 短語 。
如果子樹高度為2,那麼這棵子樹的邊緣稱為該句型的一個 直接短語 。
直接短語一定是某產生式的右部,但反之不一定。
如果一個文法可以為某個句子生成 多棵分析樹 ,則稱這個文法是 二義性的 。
二義性原因:多個if只有一個else;
消岐規則:每個else只與最近的if匹配。
⑨ 鍩虹路緙栬瘧鍘熺悊
娣卞叆鎺㈢儲緙栬瘧鍘熺悊錛氫粠鍩虹鍒伴珮綰цВ鏋
涓銆佺紪璇戠▼搴忕殑濂ョ
緙栬瘧鍣錛岃繖搴ч氬線鏈哄櫒璇璦鐨勬ˉ姊侊紝灝嗘簮浠g爜鐨勯瓟娉曡漿鍖栦負鏈哄櫒鑳界悊瑙g殑鎸囦護銆傚畠鐨勬棶紼嬪垎涓哄叚姝ワ細璇嶆硶鍒嗘瀽錛堝皢婧愪唬鐮佸垎鍓蹭負涓涓涓鍙璇嗗埆鐨勫崟鍏冿級銆佽娉曞垎鏋愶紙瑙f瀽浠g爜緇撴瀯錛夈佽涔夊垎鏋愶紙璧嬩簣姣忎釜絎﹀彿鎰忎箟錛夈佷腑闂翠唬鐮佺敓鎴愶紙涓哄悗緇浼樺寲鍋氬噯澶囷級銆佷唬鐮佷紭鍖栵紙鎻愬崌鏁堢巼錛夊拰鐩鏍囦唬鐮佺敓鎴愶紙鐢熸垚鏈緇堝彲鎵ц屾枃浠訛級銆傜紪璇戣繃紼嬪閥濡欒繍鐢ㄨ〃鏍肩$悊錛屽墠絝璁捐℃椂鐩鏍囨満鏃犲叧錛岃屽悗絝璁捐″垯緔у瘑緇戝畾鐩鏍囧鉤鍙扮壒鎬с
浜屻佽В閲婄▼搴忎笌緙栬瘧紼嬪簭鐨勫樊寮
涓庣紪璇戠▼搴忎笉鍚岋紝瑙i噴鍣ㄩ愯屾墽琛屾簮浠g爜錛屼笉鐢熸垚鍙鎵ц屾枃浠訛紝榪欎嬌寰楄В閲婄▼搴忚櫧鐒舵槗浜庤皟璇曪紝浣嗛熷害杈冩參涓斿崰鐢ㄥ唴瀛樿緝澶с
涓夈佽娉曚笌鏂囨硶鐨勬ˉ姊
璇璦鐨勮摑鍥劇敱璇娉曞拰璇涔夊叡鍚屾瀯寤恆備笂涓嬫枃鏃犲叧鏂囨硶錛屽傚悓璇璦鐨勯氱敤璇娉曡勫垯錛屾槸鎻忚堪鍜岀悊瑙h璦緇撴瀯鐨勫叧閿宸ュ叿銆
鍥涖佺粓緇撶︿笌闈炵粓緇撶︾殑瀵嗙爜
緇堢粨絎︼紝濡傚悓璇璦鐨勫熀鏈鍏冪礌錛岄潪緇堢粨絎﹀垯鏄鐢辯粓緇撶﹀拰鏂囨硶瑙勫垯緇勫悎鑰屾垚鐨勬娊璞℃傚康錛屽叡鍚屾瀯鎴愪簡璇璦鐨勫熀鐭熾
浜斻丒BNF錛氭墿灞曠殑璇娉曟弿榪扮
EBNF錛圗xtended Backus-Naur Form錛夋槸涓縐嶅己澶х殑絎﹀彿琛ㄧず娉曪紝鐢ㄤ簬娓呮櫚瀹氫箟澶嶆潅璇璦緇撴瀯錛屾棤璁烘槸綆鍗曠被鍨嬭繕鏄鑷瀹氫箟綾誨瀷錛岄兘鍙閫氳繃瀹冪簿鍑嗗畾涔夈
鍏銆佹帰緔㈣璦鐨勭﹀彿涓栫晫
閫氳繃瀛楁瘝琛▄0, 1}錛屾垜浠鍙浠ユ瀯閫犲嚭濡00銆10榪欐牱鐨勭﹀彿涓層備覆榪炴帴銆佸籙榪愮畻鍜岄泦鍚堣繍綆楋紝濡侫={a, b}脳B={c, d} = {ac, ad, bc, bd}錛屽睍紺轟簡絎﹀彿涓茬殑涓板瘜鎬с傞棴鍖呮傚康鎻紺轟簡鎵鏈夋湁闄愰暱涓茬殑闆嗗悎鐗規с
涓冦佹枃娉曠殑鏋勯犱笌瑙f瀽
鏂囨硶鐢遍潪緇堢粨絎﹂泦銆佺粓緇撶﹂泦銆佽勫垯闆嗗拰璇嗗埆絎︾粍鎴愶紝濡俛->b錛屾枃娉曚功鍐欎負G[S]銆傛帹瀵間笌瑙勭害灞曠ず浜嗚璦鏋勯犵殑閫昏緫錛屽彞鍨嬪拰璇璦鍒欐槸鏂囨硶浣滅敤鐨勪綋鐜幫紝涔斿嗘柉鍩哄洓鍨嬫枃娉曞睍紺轟簡閫掑綊鍜屼笂涓嬫枃鐩稿叧鎬х殑涓嶅悓灞傛°
鍏銆佽娉曟爲錛氳璦鐨勭粨鏋勪箣緹
璇娉曟爲鐘瑰傜紪璇戠殑钃濆浘錛屾瘡涓鑺傜偣鏍囪頒負V絎﹀彿錛屼粠鏍硅妭鐐筍鍑哄彂錛岄伒寰鐗瑰畾瑙勫垯錛岀洿瑙傛彮紺哄彞鍨嬫帹瀵肩殑緇撴瀯銆
涔濄佽勮寖鎺ㄥ間笌鍙ュ瀷鍒嗘瀽
瑙勮寖鎺ㄥ肩『淇濊В鏋愯繃紼嬬殑鍞涓鎬э紝娑堥櫎浜屼箟鎬э紝鑰屽彞鍨嬪垎鏋愬垯閫氳繃鑷涓婅屼笅鎴栬嚜涓嬭屼笂鐨勬柟娉曪紝楠岃瘉絎﹀彿涓叉槸鍚︾﹀悎鏂囨硶銆
鍗併佺Щ榪-褰掔害鍒嗘瀽涓庝紭鍏堝垎鏋愭硶
縐昏繘-褰掔害鍒嗘瀽灝嗚緭鍏ラ愪釜瑙f瀽錛岀畻絎︿紭鍏堝垎鏋愬垯鏍規嵁榪愮畻絎︿紭鍏堢駭鍐沖畾鎿嶄綔欏哄簭銆備笁縐嶄紭鍏堝叧緋誨畾涔変簡鍒嗘瀽鐨勭簿緇嗘ラわ紝浠庣畝鍗曚紭鍏堝埌綆楃︿紭鍏堬紝鏁堢巼鍜岄傜敤鑼冨洿鍚勫紓銆
鍗佷竴銆丩R鍒嗘瀽鍣錛氳В鏋愮殑寮哄ぇ宸ュ叿
LR鍒嗘瀽鍣ㄦ槸瑙f瀽澶嶆潅鏂囨硶鐨勫己澶ф﹀櫒錛屽畠閫氳繃ACTION琛ㄥ拰GOTO琛錛屼互鍙婃枃娉曠﹀彿鍜岀姸鎬佺殑宸у欑$悊錛岀『淇濊В鏋愮殑楂樻晥鍜屽噯紜鎬с
鍗佷簩銆佹爤鍦ㄨВ鏋愪腑鐨勮掕壊
鏍堝湪褰掔害銆佹帴鍙楀拰鎶ラ敊榪囩▼涓鎵婕斿叧閿瑙掕壊錛屽綊綰︽椂璋冩暣鐘舵侊紝鎺ュ彈鏃剁『璁ゅ紑濮嬶紝閿欒鏃跺垯鍙戝嚭璀﹀憡銆侺R鍒嗘瀽鍣ㄧ殑鍏抽敭鍦ㄤ簬鍒嗘瀽琛ㄧ殑鏋勫緩錛屽喅瀹氫簡瑙f瀽鍣ㄧ殑鎬ц兘鍜屾g『鎬с
鍗佷笁銆丩R(0)鍒嗘瀽鐨勭簿濡欎箣澶
媧誨墠緙DFA鐨勬瀯寤猴紝閫氳繃姝h勮〃杈懼紡鍜岄」鐩闆嗚勮寖鏃忥紝鎻紺轟簡LR(0)鍒嗘瀽鐨勬繁灞傞昏緫錛屽畠鍦ㄧ畝鍖栧啿紿佸勭悊鐨勫悓鏃訛紝鍏奸【浜嗗瓨鍌ㄦ晥鐜囧拰瑙f瀽鑳藉姏銆
緙栬瘧鍘熺悊鐨勬棶紼嬫繁鍏ヨ屼赴瀵岋紝姣忎竴鐜鑺傞兘濡傚悓璇璦鐨勬瀯閫犱箰璋憋紝浜ょ粐鍑鴻$畻鏈虹戝︾殑浜ゅ搷涔愮珷銆備粠鍩虹鐨勮勫垯瑙f瀽錛屽埌楂樼駭鐨勫垎鏋愭柟娉曪紝姣忎竴絝犻兘涓虹悊瑙d唬鐮佽儗鍚庣殑閫昏緫鎻愪緵浜嗗叧閿鐨勬ˉ姊併
⑩ C語言編譯原理是什麼
編譯共分為四個階段:預處理階段、編譯階段、匯編階段、鏈接階段。
1、預處理階段:
主要工作是將頭文件插入到所寫的代碼中,生成擴展名為「.i」的文件替換原來的擴展名為「.c」的文件,但是原來的文件仍然保留,只是執行過程中的實際文件發生了改變。(這里所說的替換並不是指原來的文件被刪除)
2、匯編階段:
插入匯編語言程序,將代碼翻譯成匯編語言。編譯器首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤後,編譯器把代碼翻譯成匯編語言,同時將擴展名為「.i」的文件翻譯成擴展名為「.s」的文件。
3、編譯階段:
將匯編語言翻譯成機器語言指令,並將指令打包封存成可重定位目標程序的格式,將擴展名為「.s」的文件翻譯成擴展名為「.o」的二進制文件。
4、鏈接階段:
在示例代碼中,改代碼文件調用了標准庫中printf函數。而printf函數的實際存儲位置是一個單獨編譯的目標文件(編譯的結果也是擴展名為「.o」的文件),所以此時主函數調用的時候,需要將該文件(即printf函數所在的編譯文件)與hello
world文件整合到一起,此時鏈接器就可以大顯神通了,將兩個文件合並後生成一個可執行目標文件。