摘要:程序預處理本章節研究的是,源代碼文件是如何一步步得到一個可執行程序的。如的語句被稱為預處理指令,還有注釋文本的刪除,都在此階段完成替換。目的是能夠將所有文件中的代碼組合到一起成一個完整的程序。終止程序可以正常也可以意外終止程序。
本章節研究的是,源代碼文件
test.c
是如何一步步得到一個可執行程序test.exe
的。在之前的學習中可知.c
文件要先后經過編譯鏈接成.exe
文件再執行。
程序的編譯鏈接運行如下圖所示。翻譯中編譯又包括預編譯、編譯、匯編。
編譯鏈接執行三個步驟,都需要為其配置不同的環境。編譯和鏈接在翻譯環境中,而執行在運行環境中發生。
- 翻譯環境:在該環境中源代碼被轉換成可執行的機器指令。
- 執行環境:用于實際執行代碼。
翻譯階段的大致流程如下圖所示。
組成一個程序的每個.c
源文件都會被編譯器編譯,分別生成對應的.obj
目標文件。多個目標文件以及引入的鏈接庫被鏈接器鏈接在一起,形成一個單一的.exe
可執行程序。
編譯器即是一個用于編譯代碼的工具,在vs環境下為
cl.exe
的可執行程序。連接器則是用于鏈接所有目標文件的工具,在vs中為link.exe
的可執行程序,鏈接庫是標準中任何被該程序用到的函數。如圖:
而若想觀察翻譯代碼過程中的每一個流程的具體細節,在集成開發環境
vs
中不便展示,當然我們可以使用Linux
環境下的gcc
編譯器。
此次演示就采用加法函數,分別存放在兩個文件test.c
和add.c
。
//1. add.cint Add(int x, int y){ int sum = x + y; return sum;}//2. test.c#include //聲明函數extern int Add(int x, int y);int main(){ int a = 10; int b = 20; int ret = 0; ret = Add(a, b); printf("ret = %d/n", ret); return 0;}
Linux環境下編寫完
test.c
文件的代碼后,輸入gcc test.c -E
可以將代碼預編譯的結果輸出到屏幕上。還可以用gcc test.c -E -o test.i
是將結果輸出到文件test.i
。
如#include
,#define
,#pragma
的語句被稱為預處理指令,還有注釋文本的刪除,都在此階段完成替換。
所有可以看出預編譯階段的動作都是文本操作:
#include
頭文件的包含#define
預處理符號的替換預編譯,顧名思義,是在編譯前刪減代碼中的不必要的與機器識別代碼無關的內容。被稱為文本操作。
對預編譯產生的文件
test.i
再編譯gcc test.i -S
,會自動生成匯編代碼test.s
。
故編譯階段是將C語言代碼轉化為匯編代碼,這是整體現象。實際上會發生這四個動作:
詞法分析,語法分析,語義分析都是編譯器識別語句的操作。重點是接下接下來的符號匯總。
符號匯總,是只對全局符號進行匯總,局部符號是不進行匯總的。目的是能夠將所有文件中的代碼組合到一起成一個完整的程序。如add.c
文件中的函數名Add
,還有test.c
文件中的Add
和main
。
gcc test.s -C
將編譯結束產生的匯編代碼轉化成了二進制指令(機器指令)存入二進制文件test.o
中。
匯編階段會形成符號表,因為機器在調用指令時需要知道其存放的位置,所謂符號表大概就是符號和其地址的集合。如圖,可以假設:
鏈接將二進制指令目標文件
test.o
等,鏈接在一起形成可執行程序test.out
。目標文件test.o
是elf
格式文件,在Linux平臺下可以用readelf
翻譯并查看其內容。
鏈接階段的動作是:
所謂的鏈接,就是將對應的段合并起來。
符號表的合并,是將各自的符號表合并到一起。如test.o
中的Add
的無效地址,需把add.o
中Add
的地址合并過去再重定位到變量的真實地址,才是有意義的。
從編譯期間的符號匯總,到匯編時的形成符號表,再到鏈接時的合并和重定位符號表,都是為了最后生成可執行程序時能夠找到并鏈接各個文件中的符號。
程序首先載入內存
有的機器上有操作系統,這個動作就是由操作系統完成,沒有的由手工完成。
執行調用main
函數
創建函數棧幀
程序使用一個運行時堆棧,存儲函數的局部變量和返回地址。
終止程序
可以正常也可以意外終止程序。
程序的執行并不是本章的要點,所以就大概介紹一下。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/122008.html
摘要:學單片機多去官網上查資料,下載手冊,像我入門的單片機經常去官網,還有學的系列板子,公司的官網的官方例程給的很詳細,在英文視角閱讀對你大有益處。 目錄 1.C語言經典 2.單片機系列 3.Python方面 4.嵌入式LWip協議 5.Android 6.C++經典書籍 7.Linux開發 ...
摘要:在符號位中,表示正,表示負。我們知道對于整型來說,內存中存放的是該數的補碼。在計算機系統中,數值一律用補碼來表示和存儲。表示有效數字,。規定對于位的浮點數,最高的位是 ...
摘要:如的語句被稱為預處理指令,還有注釋文本的刪除,都在此階段完成替換。故宏在程序規模和執行速度方面更勝一籌。宏替換發生在預編譯期間,故無法調試。宏可能由于運算符優先級的問題,會導致程序出錯。 ...
目錄 ? ?一、數據類型介紹 二、類型的意義 三、類型的基本歸類 整型家族 浮點數家族 構造類型(自定義類型) 指針類型 空類型 四、整形在內存中的存儲 原碼、反碼、補碼 大小端字節序 為什么有大端和小端? 一道經典筆試題 ?一、數據類型介紹 數據從大的方向分為兩類: 內置類型自定義類型內置類型我們前面已經學習過,如下: char? ? ? ? ? ? //字符數據類型 short? ? ? ...
閱讀 1814·2021-10-09 09:44
閱讀 2690·2021-09-22 15:38
閱讀 2450·2021-09-09 09:33
閱讀 685·2021-09-07 09:58
閱讀 1784·2021-09-02 15:41
閱讀 2484·2019-08-30 15:55
閱讀 1796·2019-08-30 15:55
閱讀 533·2019-08-30 15:44