C語言翻譯環境:預編譯+編譯+匯編+鏈接詳解

目錄

翻譯環境和運行環境

翻譯環境

預處理(預編譯)

編譯

詞法分析

語法分析

?語義分析

匯編

鏈接

運行環境



?翻譯環境和運行環境

在ANSI C的任何?種實現中,存在兩個不同的環境。

  • 第1種是翻譯環境,在這個環境中源代碼被轉換為可執行的機器指令。
  • 第2種是運行環境,它用于實際執行代碼。

可執行程序中存儲的是二進制指令(機器指令)

?翻譯環境

那翻譯環境是怎么將源代碼轉換為可執行的機器指令的呢?這里我們就得展開開講解?下翻譯環境所做的事情。
其實翻譯環境是由編譯鏈接兩個大的過程組成的,而編譯?可以分解成:預處理(有些書也叫預編譯)、編譯、匯編三個過程。

?個C語言的項目中可能有多個.c文件?起構建,那多個.c文件如何生成可執行程序呢?

  • 多個.c文件單獨經過編譯器,編譯處理生成對應的目標文件(后綴為.obj)
  • 注:在Windows環境下的目標文件的后綴是.obj,Linux環境下目標文件的后綴是.o
  • 多個目標文件和鏈接庫?起經過鏈接器處理生成最終的可執行程序
  • 鏈接庫是指運行時庫(它是支持程序運行的基本函數集合)或者第三方庫。
    ?

如果再把編譯器展開成3個過程,那就變成了下面的過程:

🏲預處理(預編譯)

在預處理階段,源文件和頭文件會被處理成為.i為后綴的文件。
在(Linux) gcc 環境下想觀察一下,對 test.c 文件預處理后的.i 文件,命令如下:

  • gcc -E test.c -o test.i

預處理階段主要處理那些源文件中#開始的預編譯指令。比如:#include,#define,處理的規則如下:

  • 將所有的#define刪除,并展開所有的宏定義。
  • 處理所有的條件編譯指令,如: #if、#ifdef、#elif、#else、#endif
  • 處理#include預編譯指令,將包含的頭文件的內容插入到該預編譯指令的位置。這個過程是遞歸進行的,也就是說被包含的頭文也可能包含其他文件。
  • 刪除所有的注釋
  • 添加行號和文件名標識,方便后續編譯器生成調試信息等。
  • 或保留所有的#pragma的編譯器指令,編譯器后續會使用。

經過預處理后的 .i 文件中不再包含宏定義,因為宏已經被展開(替換)。并且包含的頭文件都被插入到 .i 文件中。所以當我們無法知道宏定義或者頭文件是否包含正確的時候,可以查看預處理后的 .i 文件來確認。

🏲編譯

編譯過程就是將預處理后的文件進行?系列的:詞法分析、語法分析、語義分析及優化,生成相應的匯編代碼文件。
編譯過程的命令如下:

gcc -S test.i -o test.s

對下面代碼進行編譯的時候,會怎么做呢?假設有下面的代碼

array[index] = (index+4)*(2+6);

?詞法分析

將源代碼程序被輸入掃描器,掃描器的任務就是簡單的進行詞法分析,把代碼中的字符分割成?系列的記號(關鍵字、標識符、字?量、特殊字符等)。

array[index] = (index+4)*(2+6);

上面程序進行詞法分析后得到了16個記號:

記號類型
array標識符
[左方括號
index標識符
]右方括號
=賦值
(左圓括號
index標識符
+加號
4數字
)右圓括號
*乘號
(左圓括號
2數字
+加號
6數字
)右圓括號

?語法分析

接下來語法分析器,將對掃描產生的記號進行語法分析,從而產生語法樹。這些語法樹是以表達式為節點的樹。

??語義分析

語義分析器來完成語義分析,即對表達式的語法層?分析。編譯器所能做的分析是語義的靜態分
析。靜態語義分析通常包括聲明和類型的匹配,類型的轉換等。這個階段會報告錯誤的語法信息

🏲匯編

匯編器是將匯編代碼轉轉變成機器可執行的指令,每?個匯編語句幾乎都對應?條機器指令。就是根據匯編指令和機器指令的對照表??地進行翻譯,翻譯成機器語言(二進制指令),也不做指令優化。
匯編的命令如下:

gcc -c test.s -o test.o


?因為編輯器格式不匹配,所以這些二進制指令展示出來的是亂碼。

🏲鏈接

鏈接是?個復雜的過程,鏈接的時候需要把?堆文件鏈接在?起才生成可執行程序。
鏈接過程主要包括:地址和空間分配,符號決議和重定位等這些步驟。
鏈接解決的是?個項目中多文件、多模塊之間互相調用的問題。
比如:
在?個C的項目中有2個.c文件( test.c 和?add.c ),代碼如下

test.c 經過編譯器處理生成 test.o?
add.c 經過編譯器處理生成?add.o?
我們在 test.c 的文件中使用了 add.c 文件中的 Add 函數和 g_val 變量。

我們在 test.c 文件中每一次使用?Add 函數g_val變量?的時候必須確切的知道 Add 和 g_val 的地址,但是由于每個文件是單獨編譯的,在編譯器編譯 test.c 的時候并不知道 Add 函數和 g_val變量的地址,所以暫時把調用?Add 的指令的目標地址和 g_val 的地址擱置。等待最后鏈接的時候由鏈接器根據引用的符號 Add 在其他模塊中查找 Add 函數的地址,然后將 test.c 中所有引用到Add 的指令重新修正,讓他們的目標地址為真正的 Add 函數的地址,對于全局變量 g_val 也是類似的方法來修正地址。這個地址修正的過程也被叫做:重定位

在編譯階段,每個.c文件都會生成一個符號表,然后在鏈接的時候進行匯總。

?運行環境

  1. 程序必須載入內存中。在有操作系統的環境中:?般這個由操作系統完成。在獨立的環境中,程序的載入必須由手動安排,也可能是通過可執行代碼置入只讀內存來完成。
  2. 程序的執行便開始。接著便調用main函數。
  3. 開始執行程序代碼。這個時候程序將使用?個運行時堆棧(stack),存儲函數的局部變量和返回地址。程序同時也可以使用靜態(static)內存,存儲于靜態內存中的變量在程序的整個執行過程?直保留他們的值。
  4. 終止程序。正常終止main函數;也有可能是意外終止。
    ?

____________________

?感謝你的閱讀,希望本文能夠對你有所幫助。如果你喜歡我的內容,記得點贊關注收藏我的博客,我會繼續分享更多的內容。?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697275.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697275.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697275.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

H橋逆變方式介紹(單極性)

H橋逆變電路實現的就是一個從DC——AC的過程 這個電路有兩個時序,Q6Q4是一個導通時序,Q5Q7是一個導通時序 左邊兩個是高頻20KHZ的、互補的sPWM波,右邊是低頻的50HZ的PWM波 三角波一般叫載波,正弦波叫調制波(單片機內…

Hbase和Clickhouse對比簡單總結

Hbase和Clickhouse是兩種不同的數據庫系統,它們各自適用于不同的場景。以下是兩者之間的對比: 數據模型: HBase 是一種基于列的存儲系統,它適合處理大規模的數據集,特別是那些需要快速隨機訪問的場景。ClickHouse 則是…

對“絕地求生“源碼調節

調整了一些界面和降低游戲難度 #include "c.h" using namespace std; ExMessage msg; struct ME {int x 100; int y 100; int life 1000; int knapsack[18]; int Maximum_ammunition_capacity 0;int Ammunition_capacity 0; int primary_weapon 0; int moveme…

springboot/ssm倉庫管理系統Java貨物出入庫管理系統wms系統web

springboot/ssm倉庫管理系統Java貨物出入庫管理系統wms系統web 基于springboot(可改ssm)vue項目 開發語言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服務器:tomcat 數據庫&#xff1a…

Vi/Vim 使用小竅門,如何消除搜索后的關鍵字高亮

Vim/Vi 基本上是 *nix 世界最受歡迎的編輯器了,不知道為什么,一直以來覺得和 Emacs 比起來,Vim 更加有親和力。用起來很舒服。 今天就記錄一個困擾了我很久的問題。 大家應該都知道,在 Vi 里面如果要搜索某個關鍵字,…

C語言開發教程

C語言開發教程 電子書下載 下載地址 第一章 導言 1.1 入門 1.2 變量與算術表達式 1.3 for語句 1.4 符號常量 1.5 字符輸入/輸出 1.6 數組 1.7 函數 1.8 參數--傳值調用 1.9 字符數組 1.10 外部變量與作用域 第二章 類型、運算符與表達式 2.1 變量名 2.2 數據類型及長度 2.3 常…

汽車會撞死人,應不應該限制汽車?

激進派表示事故率很低,損失相比汽車帶來的收益不值一提,不能限制汽車 保守派表示行人什么也沒有做錯,卻飛來橫禍,只要發生一起事故,可能對一個家庭就是滅頂之災,應該嚴格限制汽車 兩邊都有道理&#xff0c…

Python-pdfplumber讀取PDF內容

文章目錄 前言一、pdfplumber模塊1.1 pdfplumber的特點1.2 pdfplumber.PDF類1.3pdfplumber.Page類 二 pdfplumber的使用2.1 加載PDF2.2 pdfplumber.PDF 類2.3 pdfplumber.Page 類2.4 讀取PDF2.5 讀取PDF文檔信息2.6 查看總頁數2.7 查看總頁數讀取第一頁的寬度,頁高等…

263集成客服系統:提升電商平臺用戶體驗

{連接:無縫整合客服渠道} 在電子商務領域,客服是保持客戶滿意度和忠誠度的關鍵因素。263集成客服系統允許電商平臺無縫連接到各種客服通道,包括在線聊天、電子郵件和社交媒體等。這種無代碼開發方式不僅消除了傳統API開發的復雜性&#xff…

使用Java調用Cplex求解帶時間窗的車輛路徑問題

使用Java調用Cplex求解VRPTW問題 一、帶時間窗車輛路徑優化問題(Vehicle Routing Problem with Time Window,VRPTW)1.1 問題描述1.2 模型構建 二、使用Java調用Cplex求解VRPTW問題2.1 完整代碼2.2 求解結果 三、求解過程中踩的坑 一、帶時間窗…

DevOps:實現軟件開發與運維的協同革命

DevOps作為一種新型的軟件開發和運維模式,在當今信息技術領域引起了廣泛關注和應用。本文通過對DevOps的定義、原則、核心實踐以及優勢等方面進行探討,旨在深入剖析DevOps對軟件開發與運維的革命性影響,并從實踐角度探討其在現代軟件開發中的…

VsCode編譯wxWidgets的HelloWorld

wxWidgets 環境搭建 在wxWidgets 官網下載頁面點擊Download Windows Binaries選擇TDM-GCC 10.3和MinGW-w64 8.1下的頭文件和開發包進行下載。這兒我們會用兩種 gcc 編譯器進行對比,所以下載 2 個種編譯器對應的庫文件。正常只需根據自己安裝的編譯器下載對應的 1 種…

[每周一更]-(第88期):Nginx 之 proxy_pass使用詳解

proxy_pass 指令用于指定后端服務器的地址,可以采用以下不同的格式: 直接指定地址和端口: location / {proxy_pass http://backend_server:8080; }這將請求代理到 http://backend_server:8080。 使用變量: location / {set $ba…

petalinux_zynq7 驅動DAC以及ADC模塊之五:nodejs+vue3實現web網頁波形顯示

前文: petalinux_zynq7 C語言驅動DAC以及ADC模塊之一:建立IPhttps://blog.csdn.net/qq_27158179/article/details/136234296petalinux_zynq7 C語言驅動DAC以及ADC模塊之二:petalinuxhttps://blog.csdn.net/qq_27158179/article/details/1362…

flutter開發實戰-手勢Gesture與ListView滾動競技場的可滑動關閉組件

flutter開發實戰-手勢Gesture與ListView滾動競技場的可滑動關閉組件 最近看到了一個插件,實現一個可滑動關閉組件。滑動關閉組件即手指向下滑動,組件隨手指移動,當移動一定位置時候,手指抬起后組件滑出屏幕。 一、GestureDetect…

大保司保費貴,是否物有所值?

《大保司保費貴,是否物有所值》 這是羅師兄的原創文章 預計8-9分鐘讀完 作者:羅師兄 微信號:luoyun515 當我們想要買一份重疾險、儲蓄險等長期險時, 我們會發現,同樣的保障責任和保額, 不同保險公司的…

基于AdaBoost算法的情感分析研究-微博情感分析-文本分類

基于AdaBoost算法的情感分析研究 摘 要 隨著互聯網的快速發展,各類社交媒體平臺如微信、QQ等也與日俱增,而微博更是集成了傳統網站、論壇、博客等的優點,并加上了人與人之間的互動性、關系親密程度等多種智能算法,并以簡練的形式…

python安裝與配置2024最新版

對python不熟悉的可以去看看這篇文章python介紹 pytho安裝 來到Python官網:https://www.python.org/ 然后 選著download列表下的windows , 然后加進入python各個版本的下載界面 可以看到截止2024年2月22日,最新版是3.12.2 但是我們一般下載穩定版 如下,點擊連接進…

設計模式學習筆記 - 面向對象 - 5.接口和抽象類的區別

簡述 在面向對象編程中,抽象類和接口是常被用到的語法概念,是面向對象四大特性,以及很多設計模式、設計思想、設計原則實現的基礎。它們之間的區別是什么?什么時候用接口?什么時候用抽象類?抽象類和接口存…

解決兩個MySQL5.7報錯

目錄 1.啟動不了MySQL,報錯缺少MSVCR120.dll去官網下載vcredist_x64.exe運行安裝進入管理員CMD 2.本地計算機 上的 mysql 服務啟動后停止。某些服務在未由其他服務或程序使用時將自動停止,Fatal error: Can‘t open and lock privilege tables: Table ‘…