Linux中gcc/g++的基本使用

目錄

  • gcc/g++的使用
  • gcc/g++是如何生成可執行文件的
    • 預處理
    • 編譯
    • 匯編
    • 鏈接
    • .o文件是如何與庫鏈接的?
  • debug版本和release版本

gcc/g++的使用

在windows中,我們在VS中編寫好了代碼之后就可以直接在VS中對源碼進行編譯等操作后運行
而在Linux下,我們可以使用gcc/g++編譯器

gcc只能處理C語言代碼
g++可以處理C++代碼,也兼容C語言

對于一些指令和選項,在gcc和g++中是一樣的,所以本文只介紹gcc的用法

假如現在,我們已經寫好了一個C語言代碼mycode.c,那么怎么將這個代碼進行一些列處理,最后去運行它呢?

下面一條指令就可以:

gcc mycode.c

這條指令會默認讓其可執行文件命名為a.out
如果想要自定義可執行程序,可以使用選項-o

gcc mycode.c -o mycode  

這樣,生成的可執行文件就叫做mycode了,并且這個寫法是最推薦的寫法

gcc -o mycode mycode.c這樣的寫法也可,記住-o選項后面永遠跟著重命名的可執行程序名

接下來想要執行這個文件,執行指令:./mycode



gcc/g++是如何生成可執行文件的

從源碼開始,經過預處理,編譯,匯編,鏈接四個步驟后,才能生成可執行程序
在gcc中,也有相應的選項去對文件進行只預處理,只編譯,只匯編,只鏈接

下面介紹一下每個步驟的主要功能以及在gcc中相應操作
我們使用的源碼很簡單:

 #include<stdio.h>#define N 10
//主函數
int main()
{for(int i = 0;i<N;i++){printf("%d ",i);                                                                                                            }return 0;
}

預處理

在預處理階段,主要功能包括:展開頭文件,宏替換,去注釋,條件編譯
gcc中的選項為-E
-E選項告訴gcc,從現在開始進行程序的翻譯,將預處理做完就停下來,不再往后走
我們常將預處理后的文件命名為以.i后綴結尾的文件

gcc -E mycode.c -o mycode.i

其實,預處理后的文件還是c語言的代碼,只是將頭文件展開,宏替換,去注釋,條件編譯

我們可以用vim查看mycode.i文件
我們可以發現,mycode.i的代碼有800多行,原因就是將頭文件stdio.h進行了展開
查看最后面,我們可以看見自己寫的代碼,可以發現我們寫的注釋消失了,并且宏N也被替換成了10,說明也發生了去注釋和宏替換
在這里插入圖片描述

因為文中的代碼沒有涉及條件編譯,所以這里顯現不出條件編譯的結果

在這一階段,我們還可以使用-D選項進行添加宏

gcc -E mycode.c -o mycode.i -D DEBUG #添加宏DEBUG

編譯

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

gcc中,選項- S,告訴gcc,從現在開始進行程序的翻譯,將編譯工作做完就停下來,不要往后走了
我們通常將編譯后的匯編語言文件命名為.s后綴的文件

下面將mycode.i進行編譯:

gcc -S mycode.i -o mycode.s#從mycode.c還是也可以
gcc -S mycode.c -o mycode.s

進入mycode.s查看,可以看出里面是匯編代碼
在這里插入圖片描述

匯編

匯編階段就是把匯編代碼轉化成機器可以識別的二進制代碼

gcc中,選項-c,告訴gcc,從現在開始進行程序的翻譯,將匯編工作做完就停下來,不要往后走了
我們通常將編譯后的二進制機器碼文件命名為.o后綴的文件

.o文件也叫做可重定位目標二進制文件,簡稱目標文件,即windows下的.obj文件,雖然是二進制,但還不可以獨立執行,需要鏈接

gcc -c mycode.s -o mycode.o

用vim查看mycode.o文件,發現全是亂碼
在這里插入圖片描述
其實這是正確的現象,因為匯編之后文件中全是二進制的代碼,而我們用的vim是文本編輯器,它將文件以文本的形式打開,所以會將二進制代碼識別為對應的字符或符號

所以許多二進制轉化為字符或符號后,它們就會組成一篇亂碼,正如圖片所示

鏈接

這個步驟,是將可重定位二進制文件與庫進行連接成可執行文件

gcc中,連接沒有選項

gcc mycode.o -o mycode

此時,預處理,編譯,匯編,鏈接就都完成了,成功生成了可執行文件

readelf -S指令可以讀取可執行文件對應二進制構成
在這里插入圖片描述

最后,總結一下:
在這里插入圖片描述



前面講鏈接的時候提到了庫。什么是庫呢?

在C程序中,我們時常使用一些庫函數,實際上,我們使用庫函數只是在調用函數,這些庫函數的聲明在頭文件中,而庫函數的實現就是在庫中

Linux中,存放庫的目錄為/usr/lib64
C語言的標準庫:/usr/lib64/libc.so

其實庫的本質就是一個文件
在Linux中,動態庫以.so為結尾,靜態庫以.ac結尾
在Windows中,動態庫以.dll為結尾,靜態庫以.lib結尾

在Linux中,庫是有自己的命名規則的,拿動態庫為例:libname.so.xxx
而在Linux中,默認只有動態庫,靜態庫是沒有安裝的

安裝靜態庫:

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

為什么在下載完VS IDE后就可以寫程序了呢?
原因是,編譯型語言,安裝開發包,必定下載對應的頭文件和庫文件,所以可以直接進行編寫代碼

而庫就是把源文件,經過一定的翻譯,然后打包成庫,這樣就可以提供一個庫文件,不用提供太多的源文件,同時也達到了隱藏源文件的目的

頭文件提供方法的聲明,庫文件提供方法的實現+自己的代碼 = 自己的程序

庫的最主要功能就是避免重復工作,將已經實現的功能進行打包,供別人調用使用

.o文件是如何與庫鏈接的?

有2中鏈接方式:1.動態鏈接 2.靜態鏈接

動態鏈接:
動態鏈接就是所有的代碼都共用一個動態庫,所以動態庫也叫做共享庫
動態鏈接將動態庫所處的位置拷貝到可執行文件中,在運行程序時到調用庫函數的時候,會跳轉到庫中執行,執行完畢后,再跳會代碼的調用處,繼續向下執行

在這里插入圖片描述

動態庫不能缺失,一旦動態庫缺失,影響的不止是一個程序,會導致許多程序無法正常運行

在Linux中,更不能隨意刪除動態庫,因為Linux和Unix本身就是用C/C++編寫的,其中許多的命令都會調用庫函數,如果刪除了動態庫,不僅我們自己的代碼會無法運行,就連內置的命令都無法運行,此時的Linux就可以算是廢了

用指令ldd可以查看可執行程序依賴的動態庫
在這里插入圖片描述

靜態鏈接:
在編譯器使用靜態庫進行靜態鏈接時,會將自己的方法拷貝到目標程序中,使程序不再依賴靜態庫

在這里插入圖片描述
總結一下動態鏈接/庫 和 靜態鏈接/庫

  • 不論是動態庫還是靜態庫,本質上就是2個文件,里面包含了各種的源碼
  • 靜態鏈接:鏈接時,把庫中代碼拷貝自己的可執行程序里
  • 動態鏈接:在可執行程序中不拷貝實現,只是把實現所在的位置拷貝到可執行文件中
  • 靜態鏈接后,程序不再依賴靜態庫
  • 動態鏈接后,程序仍依賴動態庫

Linux中,編譯行程可執行代碼,默認采用動態鏈接
通過ldd指令可以看出,我們前面生成的可執行程序mycode依賴的是動態庫
在這里插入圖片描述
在Linux中,如果要使用靜態鏈接,要手動添加-static,并且同時系統中要有靜態庫,因為靜態庫不是系統默認提供的
下面我們將mycode.o進行靜態鏈接

gcc mycode.o -o mycode_static -static

用ldd查看,可以看出它使用靜態鏈接
在這里插入圖片描述

同時,應為與動態鏈接相比,靜態鏈接是將靜態庫中的方法實現拷貝到了可執行文件中,所以采用靜態鏈接的可執行文件的大小一定大于采用動態鏈接的可執行文件大小
在這里插入圖片描述
因為采取靜態鏈接會使可執行文件大小大很多,對于傳輸和下載這個文件會消耗許多時間和網絡,所以動態鏈接并不常用

用file指令可以查看一個可執行程序是動態鏈接的還是靜態鏈接的
在這里插入圖片描述

有幾點需要注意:

  • 如果沒有靜態庫,還添加 -static,是不行的
  • 如果沒有如果沒有動態庫,只有動態庫,并且gcc能找到,不添加-static是可以的,因為gcc默認優先動態鏈接,沒有動態庫,就使用靜態鏈接,而添加-static本質上是改變優先級
  • 一個可執行程序不一定全部是動態鏈接或靜態鏈接,也可以是混合的,因為我們的程序可能依賴各種的庫,有的庫提供了動態庫,可能有的庫沒有提供,所以可以混合使用。如果加了-static,則是讓所有鏈接都變為動態鏈接,如果庫不存在,則會報錯

動態鏈接和靜態鏈接比較:
動態鏈接的優點:動態庫是共享的,可以有效地節省資源(硬盤空間,內存空間,網絡空間等)
動態鏈接的缺點:動態庫一旦缺失,程序將無法正常運行

靜態鏈接的優點:不依賴庫,一旦形成可執行文件,可以獨立運行,可以在同平臺環境下隨便運行
靜態鏈接的缺點:體積大,占空間


debug版本和release版本

gcc默認以release模式生成可執行文件
要以debug版本生成可執行文件:

gcc mycode.c -o mycode_debug -g 

mycode_debug文件占的空間會比release版本大,因為debug可以被追蹤、調試,生成可執行文件時,向里面添加了debug信息

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

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

相關文章

LeetCode 279 —— 完全平方數

閱讀目錄 1. 題目2. 解題思路3. 代碼實現 1. 題目 2. 解題思路 此圖利用動態規劃進行求解&#xff0c;首先&#xff0c;我們求出小于 n n n 的所有完全平方數&#xff0c;存放在數組 squareNums 中。 定義 dp[n] 為和為 n n n 的完全平方數的最小數量&#xff0c;那么有狀態…

vue 展示svg矢量圖可縮放拖動

使用插件&#xff1a;svg-pan-zoom <template> <!-- svg圖--><div id"svgContainer"></div> </template><script> import svgPanZoom from svg-pan-zoom import svgFile from ../datav/img/220kVscb.svg // 路徑根據實際情況調…

MySQL存儲過程實現累加運算 1+2+…+n 等于多少?

MySQL創建存儲過程&#xff0c;實現累加運算&#xff0c;計算 12…n 等于多少。具體的代碼如下 1、實現計算123…n的和 DELIMITER // CREATE PROCEDURE sp_add_sum_num(IN n INT) BEGIN DECLARE i INT; DECLARE sum INT; SET i 1; SET sum 0;WHILE i < n DO SET sum …

若依框架實戰指南:從入門到精通

在當今快節奏的軟件開發環境中&#xff0c;選擇一個高效、可靠的開發框架至關重要。若依框架&#xff08;RuoYi&#xff09;作為一個基于Spring Boot和MyBatis的快速開發平臺&#xff0c;以其強大的功能和易用性受到了廣泛歡迎。本文將詳細介紹若依框架的使用方式&#xff0c;包…

計算機組成結構—中斷和異常

一、基本概念和分類 計算機在執行程序的過程中&#xff0c;有時會遇到一些異常情況或者特殊請求&#xff1b;這時就需要計算機暫停正在運行的程序&#xff0c;轉而先去處理這些異常或特殊請求&#xff0c;處理結束之后再返回程序的斷點處繼續執行。這種處理方式就被稱為 “中斷…

頂堅北斗有源終端有什么功能跟用途

頂堅北斗有源終端作為現代衛星導航與通信技術融合的杰出代表&#xff0c;其用途廣泛且功能強大。在廣袤無垠的偏遠山區、深邃的海洋以及荒蕪的沙漠中&#xff0c;當用戶面臨移動通信信號無法覆蓋的困境時&#xff0c;北斗有源終端便成為了連接世界的橋梁。 該終端的核心功能之一…

PE文件(六)新增節-添加代碼作業

一.手動新增節添加代碼 1.當預備條件都滿足&#xff0c;節表結尾沒有相關數據時&#xff1a; 現在我們將ipmsg.exe用winhex打開&#xff0c;在節的最后新增一個節用于存放我們要增加的數據 注意&#xff1a;飛鴿的文件對齊和內存對齊是一致的 先判斷節表末尾到第一個節之間…

奧德彪的幸福VS碼農的幸福

奧德彪的幸福 非洲國家布隆迪是一個全球最不發達國家之一&#xff0c;大部分居民以農業為生&#xff0c;其中包括香蕉&#xff0c;人們拿香蕉用來做飯也用來釀酒。 香蕉產地距離布隆迪首都布瓊布拉很遠&#xff0c;而這個國家又缺乏規模化的物流企業&#xff0c;于是就誕生了…

Linux進程--函數 system 和 popen 的區別

system() 和 popen() 是 C 語言中用于執行外部命令的兩個函數&#xff0c;它們的功能類似&#xff0c;但在使用方式和特性上有一些區別。 system() system() 函數允許您在程序中執行外部命令&#xff0c;并等待該命令執行完成后繼續執行程序。其基本語法如下&#xff1a; in…

如何使用腳本執行SQL Server 數據庫壓縮備份?

SQL Server 數據庫壓縮備份是否可以實現&#xff1f; 使用時&#xff0c;SQL Server 數據庫會變得非常大&#xff0c;備份也是如此。它們占用大量磁盤空間&#xff0c;并且每次備份數據庫或四處移動都非常耗時。因此&#xff0c;您可能想知道是否有任何方法可以創建壓縮備份。…

pikachu靶場(SQL注入基于布爾的盲注)python實現

import requests from bs4 import BeautifulSoupurl "http://localhost:8086/pikachu-master/vul/sqli/sqli_blind_b.php"def get_database_name(url):dataname # 初始化一個空字符串用于存儲數據庫名dict abcdefghijklmnopqrstuvwxyz # 數據庫名可能存在這些…

docker實戰之搭建MYSQL8.0主從同步

目錄 環境配置容器創建主服務器創建MYSQL容器新增my.cnf文件創建用戶并授權 從服務器創建MYSQL容器新增my.cnf文件重啟MYSQL容器配置主從同步 驗證主從同步彩蛋 MySQL 主從同步&#xff08;Master-Slave Replication&#xff09;是一種常用的解決方案&#xff0c;它允許一個主服…

Golang實現根據文件后綴刪除文件和遞歸刪除文件

概述 這個功能會非常強大&#xff0c;因為在日常工作中&#xff0c;我通常會遇到需要批量刪除文件的場景&#xff0c;通過這個方法&#xff0c;再結合我的另一個 命令行開發框架&#xff0c;能夠很輕松的開發出這個功能。 代碼 package zdpgo_fileimport ("errors"…

LabVIEW與串口通訊在運行一段時間后出現數據接收中斷的問題

這些問題可能與硬件、軟件或通信協議有關。以下是詳細的原因分析和可能的解決方案&#xff1a; 一、硬件原因 串口線纜或接口問題&#xff1a; 由于長時間使用&#xff0c;串口線纜可能出現接觸不良或損壞。接口松動也可能導致通訊中斷。 解決方案&#xff1a;檢查并更換串口…

C語言基礎-內存申請和釋放

在C語言中&#xff0c;malloc 和 free 是用于動態內存分配和釋放的函數。而在C中&#xff0c;new 和 delete 提供了類似的功能&#xff0c;但它們之間有一些重要的區別。 1. malloc 和 free malloc malloc 函數用于在堆上動態地分配指定字節數的內存。它的原型在 stdlib.h 頭…

【Text2SQL 經典模型】X-SQL

論文&#xff1a;X-SQL: reinforce schema representation with context ???? Microsoft, arXiv:1908.08113 X-SQL 與 SQLova 類似&#xff0c;使用 BERT style 的 PLM 來獲得 representation&#xff0c;只是融合 NL question 和 table schema 的信息的方式不太一樣&#…

一種獲取java代碼結構的實現思路

一種獲取java代碼結構的實現思路 有時,我們需要獲取java文件里的代碼結構,即,只需要里面的class定義、方法聲明、屬性定義。不需要額外的方法實現 這里提供一下實現思路: 采用語法解析器Tree-sitter對java代碼進行解析,獲取里面的方法實現遍歷第一步獲取到的方法列表,在源…

Linux c開發線程鎖和條件變量使用

#include <pthread.h> #include <stdio.h> #include <unistd.h>pthread_mutex_t mutex PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond PTHREAD_COND_INITIALIZER;void* thread_function(void* arg) {printf("線程等待喚醒,鎖定互斥量...\n");…

代碼隨想錄算法訓練營第十七天 | 110. 平衡二叉樹、257. 二叉樹的所有路徑、404. 左葉子之和

[LeetCode] 110. 平衡二叉樹 [LeetCode] 110. 平衡二叉樹 文章解釋 [LeetCode] 110. 平衡二叉樹 視頻解釋 給定一個二叉樹&#xff0c;判斷它是否是 平衡二叉樹 示例 1&#xff1a; 輸入&#xff1a;root [3,9,20,null,null,15,7] 輸出&#xff1a;true示例 2&#xff1a; 輸…

HTTP 響應分割漏洞

HTTP 響應分割漏洞 1.漏洞概述2.漏洞案例 1.漏洞概述 HTTP 響應拆分發生在以下情況&#xff1a; 數據通過不受信任的來源&#xff08;最常見的是 HTTP 請求&#xff09;進入 Web 應用程序。該數據包含在發送給 Web 用戶的 HTTP 響應標頭中&#xff0c;且未經過惡意字符驗證。…