編譯器gcc/g++ --【Linux基礎開發工具】

文章目錄

  • 一、背景知識
  • 二、gcc編譯選項
    • 1、預處理(進行宏替換)
    • 2、編譯(生成匯編)
    • 3、匯編(生成機器可識別代碼)
    • 4、鏈接(生成可執行文件或庫文件)
  • 三、動態鏈接和靜態鏈接
  • 四、靜態庫和動態庫
    • 1、動靜態庫
    • 2、編譯器自舉
      • 自舉的基本步驟
  • 五、gcc其他常用選項 - 了解即可

一、背景知識

  1. 預處理(進行宏替換/去注釋/條件編譯/頭文件展開等)
  2. 編譯(生成匯編)
  3. 匯編(生成機器可識別代碼)
  4. 連接(生成可執行文件或庫文件)

二、gcc編譯選項

格式 gcc [選項] 要編譯的文件 [選項] [目標文件]

1、預處理(進行宏替換)

? 預處理功能主要包括: 宏定義,文件包含,條件編譯,去注釋等。

? 預處理指令是以 # 號開頭的代碼行。

? 實例: gcc –E hello.c –o hello.i

? 選項 “-E” ,該選項的作用是讓 gcc 在預處理結束后停止編譯過程。

? 選項 “-o” 是指目標文件, “.i” 文件為已經過預處理的C原始程序。

2、編譯(生成匯編)

? 在這個階段中,gcc 首先要檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤后, gcc 把代碼翻譯成匯編語言。

? 用戶可以使用“-S”選項來進行查看,該選項只進行編譯而不進行匯編,生成匯編代碼。

? 實例: gcc –S hello.i –o hello.s

3、匯編(生成機器可識別代碼)

? 匯編階段是把編譯階段生成的“.s”文件轉成目標文件

? 讀者在此可使用選項“-c”就可看到匯編代碼已轉化為“.o”的二進制目標代碼了

? 實例: gcc –c hello.s –o hello.o

4、鏈接(生成可執行文件或庫文件)

? 在成功編譯之后,就進入了鏈接階段。

? 實例: gcc hello.o –o hello

三、動態鏈接和靜態鏈接

在我們的實際開發中,不可能將所有代碼放在一個源文件中,所以會出現多個源文件,而且多個源文件之間不是獨立的,而會存在多種依賴關系,如一個源文件可能要調用另一個源文件中定義的函數,但是每個源文件都是獨立編譯的,即每個*.c文件會形成一個*.o文件,為了滿足前面說的依賴關系,則需要將這些源文件產生的目標文件進行鏈接,從而形成一個可以執行的程序。這個鏈接的過程就是靜態鏈接

靜態鏈接的缺點很明顯:
? 浪費空間:因為每個可執行程序中對所有需要的目標文件都要有一份副本,所以如果多個程序對同一個目標文件都有依賴,如多個程序中都調用了printf()函數,則這多個程序中都含有printf.o,所以同一個目標文件都在內存存在多個副本;
? 更新比較困難:因為每當庫函數的代碼修改了,這個時候就需要重新進行編譯鏈接形成可執行程序。但是靜態鏈接的優點就是,在可執行程序中已經具備了所有執行程序所需要的任何東西,在執行的時候運行速度快。

動態鏈接的出現解決了靜態鏈接中提到問題。動態鏈接的基本思想是把程序按照模塊拆分成各個相對獨立部分,在程序運行時才將它們鏈接在一起形成一個完整的程序,而不是像靜態鏈接一樣把所有程序模塊都鏈接成一個單獨的可執行文件。

動態鏈接其實遠比靜態鏈接要常用得多。比如我們查看下 hello 這個可執行程序依賴的動態庫,會發現它就用到了一個c動態鏈接庫:

$ ldd hellolinux-vdso.so.1 => (0x00007fffeb1ab000) libc.so.6 => /lib64/libc.so.6 (0x00007ff776af5000) /lib64/ld-linux-x86-64.so.2 (0x00007ff776ec3000)
# ldd命令用于打印程序或者庫文件所依賴的共享庫列表。

在這 里涉及到一個重要的概念: 庫
? 我們的C程序中,并沒有定義“printf”的函數實現,且在預編譯中包含的“stdio.h”中也只有該函數的聲明,而沒有定義函數的實現,那么,是在哪 里實“printf”函數的呢?

? 最后的答案是:系統把這些函數實現都被做到名為 libc.so.6 的庫文件中去了,在沒有特別指定時,gcc 會到系統默認的搜索路徑“/usr/lib”下進行查找,也就是鏈接到libc.so.6 庫函數中去,這樣就能實現函數“printf”了,而這也就是鏈接的作用

四、靜態庫和動態庫

1、動靜態庫

? 靜態庫是指編譯鏈接時,把庫文件的代碼全部加入到可執行文件中,因此生成的文件比較大,但在運行時也就不再需要庫文件了。其后綴名一般為“.a”

? 動態庫與之相反,在編譯鏈接時并沒有把庫文件的代碼加入到可執行文件中,而是在程序執行時由運行時鏈接文件加載庫,這樣可以節省系統的開銷。動態庫一般后綴名為“.so”,如前面所述的 libc.so.6 就是動態庫。gcc 在編譯時默認使用動態庫。完成了鏈接之后,gcc 就可以生成可執行文件,如下所示。 gcc hello.o –o hello

? gcc默認生成的二進制程序,是動態鏈接的,這點可以通過 file 命令驗證。

📌 注意:
? Linux下,動態庫XXX.so, 靜態庫XXX.a
? Windows下,動態庫XXX.dll, 靜態庫XXX.lib

一般我們的云服務器,C/C++的靜態庫并沒有安裝,可以采用如下方法安裝

# Centos
yum install glibc-static libstdc++-static -y
#ubuntu(apt)

2、編譯器自舉

編譯器自舉(Bootstrapping)是指通過現有的編譯工具來構建新的編譯器的過程,尤其是指用目標語言本身編寫的新編譯器。這個過程的核心思想在于“自我宿主”——即一個高級語言程序可以用來編譯其自身的源代碼。

自舉的基本步驟

  1. 初始階段:從零開始創建一個小規模、功能有限的編譯器版本A0。它可以將一小部分核心語法結構翻譯為目標機器碼或其他中間表示形式。

  2. 迭代改進:利用現有編譯器(可能是手工編寫的簡單解釋器或者是另一種成熟語言提供的編譯系統),把更復雜的特性逐步加入到新編譯器中,并能夠處理更多的語言特性和優化技術。此時會產生一個新的編譯器版本A1。

  3. 循環增強:隨著每一輪迭代,編譯器的功能越來越強大,直到它能完全理解和轉換整個預期的目標語言為止。最終得到的就是全功能版的編譯器An,而該編譯器已經可以用自身生成的二進制文件來進行后續更新和發展了。

  4. 驗證一致性:為了保證質量,在每次升級過程中都需要進行嚴格的測試,確保每個新版本都能正確解析并編譯舊版本所支持的所有合法輸入。

  5. 獨立運行:一旦成功完成所有輪次的迭代并且經過充分調試之后,就可以移除對原始輔助編譯環境的需求,使得最終產物成為一個獨立運作的產品。

實際案例
許多現代編程語言都是采用這種方式發展的,例如GCC (GNU Compiler Collection) 的開發就是基于C/C++本身的;還有像Python這樣的腳本語言也經歷了類似的發展路徑,其中CPython實現了Python標準庫以及解釋器的主要組成部分。

五、gcc其他常用選項 - 了解即可

? -E 只激活預處理,這個不生成文件,你需要把它重定向到一個輸出文件 里面
? -S 編譯到匯編語言不進行匯編和鏈接
? -c 編譯到目標代碼
? -o 文件輸出到 文件
? -static 此選項對生成的文件采用靜態鏈接
? -g 生成調試信息。GNU 調試器可利用該信息。
? -shared 此選項將盡量使用動態庫,所以生成文件比較小,但是需要系統由動態庫.
? -O0
? -O1
? -O2
? -O3 編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為缺省值,-O3優化級別最高
? -w 不生成任何警告信息。
? -Wall 生成所有警告信息。

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

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

相關文章

Java 注解與元數據

Java學習資料 Java學習資料 Java學習資料 一、引言 在 Java 編程中,注解(Annotation)和元數據(Metadata)是兩個重要的概念。注解為程序提供了一種在代碼中嵌入額外信息的方式,這些額外信息就是元數據。元…

操作系統指定用戶密碼永不過期

背景 實際生產環境中,數據中心操作系統通常會有基線要求(比如等保之類),要求設置操作系統密碼有效期,但是infra團隊或者操作系統管理員或者某些業務配置使用的操作系統用戶又需要密碼不能不停修改(或者說一…

無用的知識又增加了:is_assignable means?

std::pair的默認operator被delete掉了,取而代之的是兩個enable_if版本。 為什么這么設計,我的理解是在std::map里,已經保存的元素的key值是不能被修改的,比如 注意,下面的代碼會修改key值,編譯時出現錯誤…

能量提升法三:贊美

前情回顧: 《能量提升法二:感恩》 片段:“感恩,就像是在跟世界說:謝謝你,我收到了,我很喜歡,請多來點” 把它歸還人海,就當作每一個人,都有可能是曾經幫助…

25美賽ABCDEF題詳細建模過程+可視化圖表+參考論文+寫作模版+數據預處理

詳情見該鏈接!!!!!! 25美國大學生數學建模如何準備!!!!!-CSDN博客文章瀏覽閱讀791次,點贊13次,收藏7次。通過了解比賽基本…

2025企業繁體鏡像站鏡像站群版 | 干擾碼+拼音插入

技術背景 高效的SEO優化和內容采集是企業站群系統的核心競爭力。本文將詳細介紹一套企業級網站鏡像工具包,重點展示其在SEO優化、內容采集、智能處理等方面的創新實現。 系統特性 1. SEO優化功能 關鍵詞智能布局標題標簽優化鏈接結構優化移動端適配頁面加速優化…

動態規劃<九>兩個數組的dp

目錄 引例 LeetCode經典OJ題 1.第一題 2.第二題 3.第三題 4.第四題 5.第五題 6.第六題 7.第七題 引例 OJ傳送門LeetCode<1143>最長公共子序列 畫圖分析&#xff1a; 使用動態規劃解決 1.狀態表示 ------經驗題目要求 經驗為選取第一個字符串的[0,i]區間以及第二個字…

大數據學習之SCALA分布式語言三

7.集合類 111.可變set一 112.可變set二 113.不可變MAP集合一 114.不可變MAP集合二 115.不可變MAP集合三 116.可變map一 package com . itbaizhan . chapter07 //TODO 2. 使用 mutable.Map 前導入如下包 import scala . collection . mutable // 可變 Map 集合 object Ma…

MongoDB中常用的幾種高可用技術方案及優缺點

MongoDB 的高可用性方案主要依賴于其內置的 副本集 (Replica Set) 和 Sharding 機制。下面是一些常見的高可用性技術方案&#xff1a; 1. 副本集 (Replica Set) 副本集是 MongoDB 提供的主要高可用性解決方案&#xff0c;確保數據在多個節點之間的冗余存儲和自動故障恢復。副…

基于OSAL的嵌入式裸機事件驅動框架——整體架構調度機制

參考B站up主【架構分析】嵌入式祼機事件驅動框架 感謝大佬分享 任務ID &#xff1a; TASK_XXX TASK_XXX 在系統中每個任務的ID是唯一的&#xff0c;范圍是 0 to 0xFFFE&#xff0c;0xFFFF保留為SYS_TSK_INIT。 同時任務ID的大小也充當任務調度的優先級&#xff0c;ID越大&#…

WGCLOUD運維工具從入門到精通 - 如何設置主題背景

需要升級到WGCLOUD的v3.5.7或者以上版本&#xff0c;才會支持自定義設置主題背景色 WGCLOUD下載&#xff1a;www.wgstart.com 我們登錄后&#xff0c;在右上角點擊如下的小圖標&#xff0c;就可以設置主題背景色了&#xff0c;包括&#xff1a;經典白&#xff08;默認&#x…

LigerUI在MVC模式下的響應原則

LigerUI是基于jQuery的UI框架&#xff0c;故他也是遵守jQuery的開發模式&#xff0c;但是也具有其特色的偵聽函數&#xff0c;那么當LigerUI作為View層的時候&#xff0c;他所發送后端的必然是表單的數據&#xff0c;在此我們以倆個div為例&#xff1a; {Layout "~/View…

基于RIP的MGRE VPN綜合實驗

實驗拓撲 實驗需求 1、R5為ISP&#xff0c;只能進行IP地址配置&#xff0c;其所有地址均配為公有IP地址&#xff1b; 2、R1和R5間使用PPP的PAP認證&#xff0c;R5為主認證方&#xff1b; R2與R5之間使用ppp的CHAP認證&#xff0c;R5為主認證方&#xff1b; R3與R5之間使用HDLC封…

git的理解與使用

本地的git git除了最經典的add commit push用來做版本管理&#xff0c;其實他的分支管理也非常強大 可以說你學好了分支管理&#xff0c;就可以完成團隊的配合協作了 git倉庫 我們可以使用git init來初始化一個git倉庫&#xff0c;只要能看見.git文件夾&#xff0c;就代表這…

Java 編程初體驗

Java學習資料 Java學習資料 Java學習資料 一、引言 在當今數字化的時代&#xff0c;編程已然成為一項極具價值的技能。而 Java 作為一門廣泛應用于企業級開發、移動應用、大數據等眾多領域的編程語言&#xff0c;吸引著無數初學者投身其中。當我們初次踏入 Java 編程的世界&…

STM32 對射式紅外傳感器配置

這次用的是STM32F103的開發板&#xff08;這里面的exti.c文件沒有how to use this driver 配置說明&#xff09; 對射式紅外傳感器 由一個紅外發光二極管和NPN光電三極管組成&#xff0c;M3固定安裝孔&#xff0c;有輸出狀態指示燈&#xff0c;輸出高電平燈滅&#xff0c;輸出…

https數字簽名手動驗簽

以bing.com 為例 1. CA 層級的基本概念 CA 層級是一種樹狀結構&#xff0c;由多個層級的 CA 組成。每個 CA 負責為其下一層級的實體&#xff08;如子 CA 或終端實體&#xff09;頒發證書。層級結構的頂端是 根 CA&#xff08;Root CA&#xff09;&#xff0c;它是整個 PKI 體…

【自然語言處理(NLP)】深度循環神經網絡(Deep Recurrent Neural Network,DRNN)原理和實現

文章目錄 介紹深度循環神經網絡&#xff08;DRNN&#xff09;原理和實現結構特點工作原理符號含義公式含義 應用領域優勢與挑戰DRNN 代碼實現 個人主頁&#xff1a;道友老李 歡迎加入社區&#xff1a;道友老李的學習社區 介紹 **自然語言處理&#xff08;Natural Language Pr…

Niagara學習筆記

橙色 發射器 , 綠色 粒子, 紅色 渲染器 Emitter State 發射器狀態 Life Cycle Mode&#xff08;生命周期模式&#xff09; 選擇Self就是發射器自身管理生命周期 Loop Behavior 決定粒子發射次數 一次&#xff08;Once&#xff09;&#xff1a;發射器只播放一次多次&#…

17 一個高并發的系統架構如何設計

高并發系統的理解 第一:我們設計高并發系統的前提是該系統要高可用&#xff0c;起碼整體上的高可用。 第二:高并發系統需要面對很大的流量沖擊&#xff0c;包括瞬時的流量和黑客攻擊等 第三:高并發系統常見的需要考慮的問題&#xff0c;如內存不足的問題&#xff0c;服務抖動的…