《Linux編譯器:gcc/g++食用指南》

堅持用 清晰易懂的圖解 + 代碼語言,讓每個知識點變得簡單!
🚀呆頭個人主頁詳情
🌱 呆頭個人Gitee代碼倉庫
📌 呆頭詳細專欄系列
座右銘: “不患無位,患所以立。”
在這里插入圖片描述


《Linux編譯器:GCC/G++食用指南》

  • 前言
  • 目錄
  • 一、gcc/g++的簡單使用
    • 1.作用
    • 2.語法
  • GCC/G++ 編譯選項速查表
  • 二、gcc/g++編譯器的執行步驟
    • 1.預處理
    • 2.編譯
    • 3.匯編
    • 4.鏈接
    • * 程序執行 *
  • 三、庫
    • 1.庫的概念
    • 2.庫的分類
    • 3 .o與庫的鏈接
    • 4.優缺點
      • **動態庫 vs 靜態庫終極對比表**


前言

🚀 歡迎來到《Linux系統實戰》!
這里是命令行到內核的躍遷基地,也是你從"rm -rf恐懼癥"到"權限管理大師"的修煉場。

🔍 專欄特色

  • 圖解+實戰:用最直觀的方式拆解Linux核心機制
  • 從應用到底層:覆蓋Shell腳本、系統調優、內核模塊開發
  • 真實場景:每篇附服務器運維/開發中的實際問題解決方案

💡 學習建議
1?? 先動手嘗試(搞崩了也沒關系)
2?? 對照文章分析原理
3?? 用文末【實戰任務】鞏固技能

📌 Linux經典名言
“Linux不是背出來的,是在一次次Permission denied中練出來的!”

(正文開始👇)


目錄

一、gcc/g++的簡單使用

1.作用

gcc和g++分別是GNU的C和C++的編譯器,gcc和g++在執行編譯的時候一般有以下四個步驟:
1)預處理(頭文件展開、去注釋、宏替換、條件編譯)。
2)編譯(C代碼翻譯成匯編語言)。
3)匯編(匯編代碼轉為二進制目標代碼)。
4)鏈接(將匯編過程產生的二進制代碼進行鏈接)。

2.語法

GCC/G++ 編譯選項速查表

選項功能說明備注
-E只進行預處理,不生成文件需手動重定向到輸出文件(如 gcc -E test.c > test.i
-S編譯到匯編語言(生成 .s 文件),不進行匯編和鏈接保留預處理 + 編譯結果
-c編譯到目標代碼(生成 .o 文件),不鏈接適用于分步編譯
-o <file>指定輸出文件名gcc test.c -o test
-static強制靜態鏈接(生成文件較大)優先鏈接靜態庫而非動態庫
-g生成調試信息(GDB 可用)默認生成 release 版本需顯式添加此選項
-shared生成動態鏈接庫(.so 文件)通常配合 -fPIC 使用
-w禁用所有警告信息不推薦使用(可能掩蓋潛在問題)
-Wall開啟所有標準警告信息實際不包括所有警告(建議結合 -Wextra
-O0不優化(調試時推薦)保留原始代碼結構
-O1基礎優化(默認級別)在編譯速度和性能間平衡
-O2深度優化(推薦發布使用)包含大多數安全優化選項
-O3激進優化(可能增加代碼體積)可能改變程序行為(需嚴格測試)

小技巧

  • 組合使用示例:g++ -Wall -O2 -g main.cpp -o app
  • 查看完整選項:gcc --helpman gcc

二、gcc/g++編譯器的執行步驟

gcc和g++的執行步驟中的指令都是相同的,這里小編以linux中的gcc編譯器的執行步驟中的指令為例進行講解

1.預處理

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

  • 預處理指令是以#號開頭的代碼行。
  • 實例: gcc –E hello.c –o hello.i
  • 選項“-E”,該選項的作用是讓 gcc 在預處理結束后停止編譯過程。
  • 選項“-o”是指目標文件,“.i”文件為已經過預處理的C原始程序。
    在這里插入圖片描述
  1. 去掉注釋
    注釋是寫給開發者人員的自然對于程序的編譯自然無用,所以編譯器將對于編譯階段無用的注釋去掉
  2. 頭文件的展開
    頭文件既然可以進行展開,那么說明在系統路徑下一定有地方存放頭文件,在預處理階段將頭文件的內容拷貝到源文件中
  3. 條件編譯
    可以支持對代碼的裁剪工作,例如應用的社區版和免費版其實就是應用了條件編譯,使同一份代碼經過條件編譯后呈現出兩種不同的狀態
  4. 宏替換
    特別講解一下這里的宏替換不進行語法檢查,我們知道在編譯階段進行語法的檢查,而宏替換是在編譯階段之前,即預處理階段已經完成了宏替換,即預處理完之后由于宏已經被替換了,所以此時宏就沒有了,自然在進行編譯階段不進行宏替換的語法檢查。

在這里插入圖片描述

2.編譯

gcc -S code.i -o code.s

gcc -S 要進行編譯的文件名(建議使用預處理后以 .i 為后綴的文件) -o 編譯后的文件名(這里建議使用 .s 為后綴),即告訴編譯器從現在開始進行翻譯,當編譯工作完成后,就停下來
在這里插入圖片描述

  • 在這個階段中,gcc/g++首先檢查代碼的規范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤后,將代碼翻譯成匯編語言。
  • 用戶可以使用-S選項來進行查看,該選項只進行編譯而不進行匯編,生成匯編代碼。
  • -o選項是指目標文件,“xxx.s”文件為已經過翻譯的原始程序。
    在這里插入圖片描述

3.匯編

gcc -c code.s -o code.0

gcc -c 要進行匯編的文件名(這里建議使用編譯后的.s文件) -o 匯編后的文件名(這里建議使用.o為后綴的文件名),告訴編譯器開始進行程序的翻譯,當匯編工作完成后,就停下來
在這里插入圖片描述

  • 匯編階段是把編譯階段生成的“xxx.s”文件轉成目標文件。
  • 使用-c選項就可以得到匯編代碼轉化為“xxx.o”的二進制目標代碼了。
    在這里插入圖片描述

4.鏈接

gcc code.o -o code

gcc 要進行鏈接的文件(這里建議使用執行完匯編后生成的.o文件) -o 鏈接后的文件名,將編譯生成的可重定位目標二進制文件(目標文件)和庫進行鏈接生成可執行程序
在這里插入圖片描述

  • 在成功完成以上步驟之后,就進入了鏈接階段。
  • 鏈接的主要任務就是將生成的各個“xxx.o”文件進行鏈接,生成可執行文件。
  • gcc/g++不帶-E、-S、-c選項時,就默認生成預處理、編譯、匯編、鏈接全過程后的文件。
  • 若不用-o選項指定生成文件的文件名,則默認生成的可執行文件名為a.out。
    在這里插入圖片描述
    注意: 鏈接后生成的也是二進制文件。

* 程序執行 *

./可執行文件名,即可執行可執行文件
在這里插入圖片描述

三、庫

1.庫的概念

  • 在鏈接的時候會進行匯編生成的二進制文件和庫進行鏈接,那么這個庫具體是指的是什么呢?
  • 拿c語言程序中的printf函數來說,在程序中調用printf打印hello,#include <stdio.h>頭文件中是printf函數的聲明,那么實現究竟是在哪里呢?沒錯,在庫中,
  • 在庫中提供函數方法的實現,在c語言中即為c語言標準庫
    庫的本質是文件,有其對應的路徑在linxu中為(動態庫)/usr/lib64/libc.so或(靜態庫)/usr/lib64/libc.a

2.庫的分類

  1. linux:.so(動態庫) .a(靜態庫)
  2. windows:.dll(動態庫) .lib(靜態庫)
  3. 系統默認只提供動態庫,為/usr/lib64/libc.so,但是對于靜態庫/usr/lib64/libc.a系統默認不提供即沒有進行安裝,這時候我們就要自行去安裝靜態庫或動態庫

動態庫

# 安裝運行時庫(僅動態庫,無頭文件)
sudo yum install curl# 安裝開發包(包含頭文件和動態庫鏈接)
sudo yum install libcurl-devel

在這里插入圖片描述
靜態庫

yum install glibc-static libstdc++-static -y

在這里插入圖片描述

方法的實現其實就在庫中
庫其實是將源文件經過翻譯,打包成為一個文件(不用提供太多的源文件,也達到了隱藏源文件的目的),庫避免了一些經常性使用的函數實現的重復書寫,節省工作,提高效率
你的軟件=頭文件提供聲明+庫提供函數的實現+你的代碼

3 .o與庫的鏈接

庫分為動態庫(共享庫)和靜態庫,那么對應有動態鏈接和靜態鏈接
動態鏈接:

  1. 動態鏈接是在程序執行時由運行時的鏈接文件加載庫,所以很多程序的運行都要依賴動態庫的存在,所以動態庫不能缺失,一旦缺失會造成很多程序無法運行,進而可能造成無法使用操作系統
  2. 靜態鏈接:
    編譯器在使用靜態庫進行靜態鏈接的時候,會將靜態庫的方法拷貝到目標程序中,需要使用哪些函數方法就將哪些函數方法拷貝到目標文件中,并不是將靜態庫的所有方法都拷貝到目標文件中,這一點經常被混淆,請讀者友友們注意區分,此后程序的執行不再需要依賴靜態庫在linux中,編譯形成可執行程序,默認采用的鏈接方式是動態鏈接—動態庫

ldd 可執行程序 可以查看或打印一個程序運行所需的共享庫
在這里插入圖片描述

觀察一下靜態鏈接方式由于是將庫進行拷貝,所以占用空間明顯大于動態鏈接(程序執行時由運行的鏈接文件進行加載庫)方式在這里插入圖片描述

  • 如果沒有靜態庫,我們不能使用-static進行靜態鏈接
  • 如果沒有動態庫,只有靜態庫,并且編譯器gcc可以找到靜態庫,此時編譯器采用靜態鏈接將我們的目標文件和庫進行鏈接,因為當系統中存在動態庫的時候,系統會優先采用動態鏈接,當不存在動態庫的時候,編譯器會再去看看系統中有沒有靜態庫,如果有靜態庫則采用靜態鏈接的方式,如果連靜態庫都沒有則報錯
  • 同時在我們的可執行文件中,并不是所有的鏈接方式都是純動態鏈接的,而是動態鏈接和靜態鏈接混合的方式
  • file 可執行程序,可以查看我們的可執行程序的鏈接方式
    在這里插入圖片描述

4.優缺點

以下是符合 CSDN 博客風格的 Markdown 表格,對比動態庫和靜態庫的優缺點,并優化了可讀性和技術專業性:


動態庫 vs 靜態庫終極對比表

特性動態庫(.so/.dll)靜態庫(.a/.lib)
🔧 編譯方式編譯時記錄依賴,運行時加載編譯時直接嵌入到可執行文件中
📦 文件體積? 極小(僅記錄符號)
? 多個程序共享同一份庫文件
? 巨大(庫代碼直接復制到程序)
? 每個程序都包含完整庫代碼
🏃 運行依賴? 必須存在
? 缺失時報錯:error while loading shared libraries
? 完全獨立
? 單文件即可運行
🔄 更新維護? 熱更新
? 替換 .so 文件立即生效
? 需重新編譯
? 修復庫=重新發布所有程序
? 運行性能?? 略慢(首次加載需解析符號)? 極致快(無運行時鏈接開銷)
💣 兼容性? 地獄級難題
? glibc 版本沖突常見
? 無煩惱
? 庫和程序成綁定關系
🛡? 安全性?? 有風險
? 可能被惡意替換成釣魚庫
? 鐵布衫
? 代碼全內嵌防篡改
🚀 適用場景? 桌面應用(如WPS)
? 微服務容器
? 插件系統(如Nginx模塊)
? 嵌入式設備
? 路由器固件
? 安全敏感工具(如tcpdump
💻 部署難度? 需處理依賴樹
? LD_LIBRARY_PATH/rpath 配置復雜
? 雙擊即用
? 無環境依賴

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

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

相關文章

SparkKV轉換算子實戰解析

目錄 KV算子 parallelizePairs mapToPair mapValues groupByKey reduceByKey sortByKey 算子應用理解 reduceByKey和groupByKey的區別 groupByKeymapValues實現KV數據的V的操作 改進用reduceByKey groupby通過K和通過V分組的模板代碼 問題集錦 寶貴的經驗 這里會…

深度解析 TCP 三次握手與四次揮手:從原理到 HTTP/HTTPS 的應用

TCP 的三次握手和四次揮手是網絡通信的基石&#xff0c;無論是 HTTP 還是 HTTPS&#xff0c;它們都依賴 TCP 提供可靠的傳輸層服務。本文將用萬字篇幅&#xff0c;結合 Mermaid 圖表和代碼示例&#xff0c;深入講解 TCP 三次握手、四次揮手的原理、過程、狀態變化&#xff0c;以…

Hyper-V + Centos stream 9 搭建K8s集群(一)

一、創建虛擬機一臺32G內存&#xff0c;16核心的Win11&#xff0c;已經安裝了Hyper-V 管理器。然后也下載了CentOS-Stream-9-latest-x86_64-dvd1.iso的鏡像文件。這里Hyper-V創建虛擬機的過程就不贅述了&#xff0c;如果出現虛擬機加載不到鏡像的問題&#xff0c;先把這個使用安…

Pygame如何制作小游戲

以下是 Pygame 的詳細使用指南&#xff0c;從安裝到開發完整游戲的步驟說明&#xff0c;包含代碼示例和最佳實踐&#xff1a; 一、安裝與環境配置 1. 安裝 Pygame pip install pygame2. 驗證安裝 import pygame pygame.init() print(pygame.version.ver) # 應輸出版本號&am…

@【JCIDS】【需求論證】聯合能力集成與開發系統知識圖譜

JCIDS(聯合能力集成與開發系統)知識圖譜 1. JCIDS概述 2. JCIDS的提出背景 3. JCIDS核心流程 4. JCIDS分析方法 5. JCIDS優勢 6. JCIDS與采辦系統的關系 7. JCIDS知識圖譜結構 8. 對我的啟示 9.JCIDS(聯合能力集成與開發系統)相關術語列表 10. 參考文獻 1. JCIDS概述 定義:…

每天學一個Linux命令(38):vi/vim

每天學一個 Linux 命令(38):vi/vim vi 和 vim(Vi IMproved)是 Linux 和 Unix 系統中功能強大的文本編輯器。vim 是 vi 的增強版,提供語法高亮、多級撤銷、插件支持等更多功能。掌握 vi/vim 是 Linux 系統管理員的必備技能之一。 1. 命令簡介 vi:經典的文本編輯器,幾乎…

【PZ-ZU49DR-KFB】:璞致電子 UltraScale+ RFSoC 架構下的軟件無線電旗艦開發平臺

璞致電子 PZ-ZU49DR-KFB 開發板基于 Xilinx ZYNQ UltraScale RFSoC XCZU49DR 主控制器&#xff0c;以 "ARMFPGA 異構架構" 為核心&#xff0c;融合高帶寬信號采集、高速數據處理與靈活擴展能力&#xff0c;專為專業工程師打造的軟件無線電&#xff08;SDR&#xff09…

力扣106:從中序與后序遍歷序列構造二叉樹

力扣106:從中序與后序遍歷序列構造二叉樹題目思路代碼題目 給定兩個整數數組 inorder 和 postorder &#xff0c;其中 inorder 是二叉樹的中序遍歷&#xff0c; postorder 是同一棵樹的后序遍歷&#xff0c;請你構造并返回這顆 二叉樹 。 思路 我們首先要知道中序遍歷和后序…

IDEA JAVA工程入門

Maven配置&#xff1a; IDEA -> settings -> Build, Execution, Deployment -> Build Tools -> MavenMaven home pathUser setting file : 特定倉庫下載依賴包&#xff0c;自動下載(界面右邊M圖標點開&#xff0c;)local repository &#xff08;本地倉庫&#xff…

Spring依賴注入:從原理到實踐的自學指南

Spring依賴注入&#xff1a;從原理到實踐的自學指南 一、什么是依賴注入&#xff1f; 依賴注入&#xff08;Dependency Injection, DI&#xff09;是Spring框架實現控制反轉&#xff08;IoC&#xff09;的核心手段。其核心思想是&#xff1a;對象不再自己創建依賴項&#xff…

3_軟件重構_組件化開發實例方法論

1、上期回顧上次內容核心的地方有兩個&#xff0c;①是C多態基類的指針指向派生類&#xff0c;用于初始化各個插件。②是使用C語言的dlopen函數“動態加載”各個插件&#xff0c;實現用戶根據契約接口自定義開發插件&#xff0c;極大程度地實現了軟件上的解耦。③再進一步&…

C#接口的定義與使用

第1章 接口&#xff08;interface&#xff09;是什么1.1 定義? 接口是一組“能力”或“契約”的抽象描述&#xff0c;只規定“能做什么”&#xff0c;不規定“怎么做”。? 在 C# 中&#xff0c;接口是一種完全抽象的類型&#xff08;fully abstract type&#xff09;。 ? 關…

【STM32】HAL庫中的實現(三):PWM(脈沖寬度調制)

&#x1f527; HAL庫中的實現&#xff1a;PWM&#xff08;脈沖寬度調制&#xff09; PWM&#xff08;Pulse Width Modulation&#xff09;是基于定時器&#xff08;TIM&#xff09;產生的周期性脈沖信號&#xff0c;廣泛應用于&#xff1a;① 電機調速&#xff1b;② LED 亮度控…

GitHub 趨勢日報 (2025年08月03日)

&#x1f680; GitHub 趨勢日報 (2025年08月03日) &#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖751dyad362LLMs-from-scratch291…

Java后端高頻面試題

Java后端高頻面試題 目錄 Java集合框架Java并發編程JVM相關MySQL數據庫Redis緩存Spring框架 Java集合框架 HashMap的數據結構是什么&#xff0c;為什么在JDK8要引入紅黑樹&#xff1f; HashMap數據結構&#xff1a; JDK7&#xff1a;數組 鏈表JDK8&#xff1a;數組 鏈表…

37. line-height: 1.2 與 line-height: 120% 的區別

概述 line-height 是 CSS 中用于控制文本行間距的重要屬性。雖然 line-height: 1.2 和 line-height: 120% 看似相同&#xff0c;但它們在計算方式上存在關鍵區別&#xff0c;尤其是在繼承和計算值方面。1. 計算方式不同寫法類型計算方式說明line-height: 1.2無單位&#xff08;…

藍橋杯----DS1302實時時鐘

&#xff08;六&#xff09;、DS1302實時時鐘1、原理&#xff08;圖 二十六&#xff09;DS1302通過三線串行接口與單片機進行通信。微控制器可以通過設置RST引腳為高電平來使能DS1302&#xff0c;并通過SCK引腳提供串行時鐘信號&#xff0c;然后通過I/O引腳進行數據的讀寫操作。…

C++對象訪問有訪問權限是不是在ide里有效

在C中&#xff0c;對象的訪問權限&#xff08;即公有&#xff08;public&#xff09;、保護&#xff08;protected&#xff09;和私有&#xff08;private&#xff09;成員的訪問&#xff09;是編譯時的一部分&#xff0c;而不是運行時。這意味著&#xff0c;無論是在IDE&#…

CubeMX安裝芯片包

1.點擊HELP2.選擇公理嵌入式軟件包3.選擇并下載芯片包

【面向對象】面向對象七大原則

設計模式 設計模式是什么&#xff1f; 設計模式是一種針對于反復提出問題的解決方案&#xff0c;是經過長時間經驗和試錯而總結出來的一套業務流程&#xff1b; 其目的是為了提高代碼的可重用性和可維護性&#xff0c;讓代碼更容易讓人理解&#xff0c;保證代碼可靠性&#…