【C語言】 —— 編譯和鏈接

【C語言】 —— 編譯和鏈接

  • 一、編譯環境和運行環境
  • 二、翻譯環境
    • 2.1、 預處理
    • 2.2、 編譯
      • (1)詞法分析
      • (2)語法分析
      • (3)語義分析
    • 2.3、 匯編
    • 2.4、鏈接
  • 三、運行環境

一、編譯環境和運行環境

??平時我們說寫 C語言 代碼,寫程序,不難發現:其實寫出來的都是 t e s t test test. c c c t e s t test test. h h h 等源文件和頭文件。我們直接打開他們,是可以直接看懂的,這也就說明了他們其實是文本文件。但是計算機是看不懂他們的,計算機只能識別二進制指令,無法對文件中的代碼直接執行。這時就需要將 C語言 代碼進行處理變成二進制的指令。
??
??而將代碼處理成二進制指令正是編譯器需要做的事情。
??
ANCI C 的任何一種實現中,存在兩個不同的環境:

  1. 翻譯環境:在這個環境中源代碼被轉換成可執行的機器指令(二進制指令)
  2. 執行環境:它用于實際執行代碼

??

二、翻譯環境

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

在這里插入圖片描述

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

  • 多個 . c c c 文件單獨經過編譯器,編譯處理生成對應的目標文件
  • W i n d o w s Windows Windows 環境下的目標文件的后綴是 .obj,在 L i n u s Linus Linus環境下目標文件的后綴是 .o
  • 多個目標文件鏈接庫一起經過連接器處理生成最終的可執行程序
  • 鏈接庫是指運行時庫(它是支持程序運行的基本函數集合)、C語言庫函數或者第三方庫

??這里需提一下,我們所用的 V S 2022 VS2022 VS2022 是一種集成開發環境,包括:編輯器編譯器鏈接器調試器。而 c l cl cl. e x e exe exe 是其編譯器, l i n k link link. e x e exe exe 是其鏈接器
??

在這里插入圖片描述

??我們可以在 L i n u s Linus Linus 服務器、 g c c gcc gcc 的環境下對鏈接和編譯各個階段進行觀察
??
??

2.1、 預處理

??在預處理階段,源文件和頭文件會被處理成 .i 為后綴的文件。

??在 g c c gcc gcc 中,將 .c 文件處理成 .h 文件,命令如下:

gcc -E test.c -o test.i

??
??預處理階段主要處理那些源文件中 # 開始的編譯指令。比如:# i n c l u d e include include,# d e f i n e define define,處理的規則如下:

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

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

在這里插入圖片描述

??
t e s t test test. i i i 文件

在這里插入圖片描述

?? . i .i .i 文件只有輸入指令生成后我們才能看到,正常情況下生成中間文件編譯器用完就刪掉了。
??
??

2.2、 編譯

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

編譯過程的命令如下:

gcc -S test.i -o test.s

??編譯過程最終會生成 .s 的文件,它里面放的是匯編代碼。其實編譯階段整體上就是將 C 代碼轉換成匯編代碼
??
t e s t . s test.s test.s 文件

在這里插入圖片描述

??那編譯過程具體是做了什么工作呢?
??他們分別是:詞法分析語法分析語義分析及優化
??下面讓我們一起簡單了解
??
??假設有下面的代碼,在進行編譯時會時編譯器怎么做呢

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

??

(1)詞法分析

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

上述代碼進行詞法分析后得到了 16 個記號:

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

??

(2)語法分析

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

在這里插入圖片描述

??

(3)語義分析

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

在這里插入圖片描述

??

2.3、 匯編

??匯編是指通過匯編器將匯編代碼轉變成機器可執行的指令,每一個匯編語句幾乎都對應一條機器指令。就是按照匯編指令和機器指令的對照表一一的進行翻譯,也不做指令優化

??匯編的命令如下:

gcc -c test.s -o test.o

??經過匯編處理后文件即為目標文件( . o b j .obj .obj / . o .o .o)目標文件為二進制文件,無法通過文本編輯器打開

??

2.4、鏈接

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

#incldue<stdio.h>//聲明外部函數
extern int Add(int x, int y);
//聲明外部的全局變量
extern int g_val;int main()
{int a = 10;int b = 20;int c = Add(10, 20);printf("%d\n", c);return 0;
}

??
A d d . c Add.c Add.c 文件

int g_val = 2024;int Add(int x, int y)
{return x + y;
}

??
??為什么在 Add.c 中定義的文件在 test.c 文件中聲明一下就可以使用呢?
??這里進行簡單的了解
??
??經過前面的學習,我們知道每一個源文件( . c .c .c)經過編譯過程后都會生成自己的目標文件 . o .o .o / . o b j .obj .obj
??
??在編譯的過程中,會對代碼中的符號進行符號的匯總,并形成相應的符號表,符號表中會存儲符號相對應的地址。在產生 t e s t . c test.c test.c 文件的符號表時,遇到只有聲明而未定義的符號 Addg_val 時,會暫時將其地址擱置

在這里插入圖片描述

??

??到了編譯過程,編譯器會將多個目標文件鏈接在一起(目標文件的格式是一樣的,并且是分段的形式),從而生成可執行程序(可執行策劃給你續最終也是如目標文件一樣的分段形式)
??
??在合并過程中,符號表也需要合并成一份。合并后的符號表每個符號只能有一份,那 Addg_val 符號自然用其有效地址的那一份,這樣符號表就完成了合并。通過 A d d Add Add 的地址,就自然而然能找到 A d d Add Add 函數了。
??

在這里插入圖片描述

??而上述對地址的修正過程被叫做:重定位
??
??前面我們非常簡潔的講解了一個 C 的程序是如何編譯和鏈接,到最終生成可執行程序的過程,其實很多內部的細節無法展開講解。
??比如:目標文件的格式 e l f elf elf,鏈接底層實現中的空間與地址分配,符號解析和重定位等,如果你有興趣,可以看 《程序員的自我修養》 一書來詳細了解。
??
??

三、運行環境

??運行環境實際上是非常復雜的,我們這里簡單了解了解

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

??
??
??
??
??


??好啦,本期關于編譯和鏈接的知識就介紹到這里啦,希望本期博客能對你有所幫助。同時,如果有錯誤的地方請多多指正,讓我們在C語言的學習路上一起進步!

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

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

相關文章

C語言中32位浮點數的格式

以 GNU C為例&#xff0c;它遵循 IEEE 754-2008標準中制定的浮點表示規范。在該規范中定義了 5種不同大小的基礎二進制浮點格式&#xff0c;包括&#xff1a;16位&#xff0c;32位&#xff0c;64位&#xff0c;128位&#xff0c;256位。其中&#xff0c;32位的格式被用作標準 C…

使用AOP思想實現開閉原則下的流水日志輸出

主要實現思想&#xff1a; 通過實現Convert接口來抽取公共組件&#xff0c;獲取想要的標準模型。 現在有兩個訂單場景&#xff0c;一個保存訂單&#xff0c;一個為更新訂單。構造如下的服務類&#xff1a; import org.springframework.stereotype.Service;Service public clas…

JavaScript-實例-button

1 需求 2 接口 3 點擊button跳轉到一個頁面 在HTML中&#xff0c;當你想要點擊一個按鈕并跳轉到另一個頁面時&#xff0c;通常你可以使用<a>標簽來包裹按鈕的樣式&#xff08;盡管這通常不是最佳實踐&#xff0c;因為<a>標簽是用于鏈接的&#xff0c;而<button&…

SHAP(SHapley Additive exPlanations)基于XGBoost模型的可解釋機器學習

模型可解釋性 這是一個關于錯誤解釋機器學習模型的危險以及正確解釋它的價值的故事。如果您發現諸如梯度提升機或隨機森林之類的集成樹模型的魯棒準確性很有吸引力&#xff0c;但也需要解釋它們&#xff0c;那么我希望您發現這些信息有用且有幫助。 試想一下&#xff0c;我們…

julia系列17: tsp問題代碼整理

1. 常用庫和基礎函數 這里是優化版的函數&#xff1a; using TSPLIB,LKH,Distances,PyPlot MaxNum 10000 tspreadTSPLIB(:att48) dist [round.(Int,euclidean(tsp.nodes[i,:],tsp.nodes[j,:])) for i in 1:tsp.dimension,j in 1:tsp.dimension]; pos(tsp::TSP,t::Vector{In…

Groovy中,多種循環方式

1.最常規的for循環 for (def i 0; i < 5; i) { //這個i需要聲明println "遍歷輸出${i}" }2.while循環 def j 0 while (j < 5) {println "遍歷輸出 ${j}"j }3.for in 循環 def list [0, 1, 2, 3, 4] //這個l無需聲明 for (l in list) { printl…

uniapp跨域問題解決

找到menifest文件&#xff0c;在文件的最后添加如下代碼&#xff1a; // h5 解決跨域問題"h5":{"devServer": {"proxy": {"/adminapi": {"target": "https://www.demo.com", // 目標訪問網址"changeOrigin…

數據庫的存儲引擎,數據類型,約束條件,嚴格模式

【一】存儲引擎 1.什么是存儲引擎存儲引擎可以理解為處理數據的不同方式 2.查看存儲引擎show engines; 3.須知的引擎MyISAM5.5之前版本MySQL默認的存儲引擎特點:存取數據的速度快 但是功能很少 安全性較低速度快因為自帶索引InnoDB5.5之后版本MySQL默認的存儲引擎特點:有諸多功…

工程施工合同無效但竣工交付,應當參照合同關于工程價款的約定計算折價補償款

審判實踐中&#xff0c;對于建設工程施工合同無效但工程竣工并交付使用的&#xff0c;應以何種標準計算折價補償款的問題&#xff0c;認識不一致。【法官會議意見】&#xff1a;建設工程施工合同是承包人進行工程建設、交付工作成果即建設工程并由發包人支付價款的合同。建設工…

httpd目錄顯示亂碼問題

vim /etc/httpd/conf/httpd.conf 在<Directory “/var/www/html”>下添加&#xff1a; IndexOptions CharsetUTF-8重啟httpd: systemctl restart httpd.service還是不好看&#xff0c;調整下顯示寬度&#xff0c;還是這個位置&#xff1a; <Directory “/var/www/ht…

區塊鏈論文速讀A會-ISSTA 2023(2/2)如何檢測DeFi協議中的價格操縱漏洞

Conference&#xff1a;ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA) CCF level&#xff1a;CCF A Categories&#xff1a;Software Engineering/System Software/Programming Languages Year&#xff1a;2023 第1~5篇區塊鏈文章 請點擊此…

09視圖,觸發器,事務,存儲過程,函數,流程控制,索引,隔離機制,鎖機制,三大范式

【一】視圖 (1)視圖須知概念 1.什么是視圖&#xff1f; 視圖就是通過查詢得到一張虛擬表&#xff0c;然后保存下來&#xff0c;下次可以直接使用 2.為什么要用視圖&#xff1f; 如果要頻繁操作一張虛擬表(拼表組成)&#xff0c;就可以制作成視圖&#xff0c;后續直接操作 注意…

IDEA 創建springboot項目雜記-更新中

一、工具使用雜記 1、使用maven 創建新springboot項目時&#xff0c;因為https://start.spring.io/ 連接不上項目無法創建。直接把腳手架地址換為國內的 http://start.aliyun.com

田忌賽馬 貪心

本題是更難的那道,一場50 最低為o 第一行一個整數 &#x1d45b;n &#xff0c;表示他們各有幾匹馬&#xff08;兩人擁有的馬的數目相同&#xff09;。第二行 &#x1d45b;n 個整數&#xff0c;每個整數都代表田忌的某匹馬的速度值&#xff08;0≤0≤ 速度值 ≤100≤1…

Python】從文本字符串中提取數字、電話號碼、日期、網址的方法

關于從文本字符串中提取數字、電話號碼、日期和網址的方法&#xff1a; 提取數字&#xff1a; 在 Python 中&#xff0c;使用正則表達式 \d 來匹配數字。 \d 表示匹配一個數字字符&#xff08;0-9&#xff09;。如果要匹配連續的數字&#xff0c;可以使用 \d 。 import re def …

C++面向對象的常見面試題目(一)

1. 面向對象的三大特征 &#xff08;1&#xff09;封裝&#xff1a;隱藏對象的內部狀態&#xff0c;只暴露必要的接口。 #include <iostream> #include <string>// 定義一個簡單的類 Person class Person { private: // 私有成員&#xff0c;外部不可直接訪問std…

Mac OS ssh 連接提示 Permission denied (publickey)

這錯誤有點奇葩&#xff0c;MacBook的IDE(vscode和pycharm)遠程都連不上&#xff0c;terminal能連上&#xff0c;windows的pycharm能連上&#xff0c;見鬼了&#xff0c;所以肯定不是秘鑰的問題了&#xff0c;查了好久竟然發現是權限的問題。。 chmod 400 ~/.ssh/id_rsa http…

華為機試HJ37統計每個月兔子的總數

華為機試HJ37統計每個月兔子的總數 題目&#xff1a; 想法&#xff1a; 上述題目實際是一個斐波那契數列&#xff0c;利用斐波那契數列對問題進行求解 input_number int(input())def fib(n):if n < 2:return 1else:n_1 1n_2 1count 2while count < n:n_1, n_2 n_…

【Android】【多屏】多屏異顯異觸調試技巧總結

這里寫目錄標題 如何獲取多屏IDs獲取多屏的size/density如何啟動應用到指定DisplayId多屏截屏/錄屏screencapscreenrecord發送按鍵到指定DisplayId 如何獲取多屏IDs dumpsys display | grep mDisplayIdtrinket:/ # dumpsys display | grep mDisplayIdmDisplayId0mDisplayId2 t…

【AI資訊】可以媲美GPT-SoVITS的低顯存開源文本轉語音模型Fish Speech

Fish Speech是一款由fishaudio開發的全新文本轉語音工具&#xff0c;支持中英日三種語言&#xff0c;語音處理接近人類水平&#xff0c;使用Flash-Attn算法處理大規模數據&#xff0c;提供高效、準確、穩定的TTS體驗。 Fish Audio