嵌入式全棧開發學習筆記---C語言筆試復習大全24

目錄

內存管理

內存分配

堆和棧的區別?(面試重點)

申請內存的函數

malloc

realloc?

free

gcc工具鏈

編譯的過程(面試重點)

第一步,預處理:

第二步,編譯:

第三步,匯編:

第四步,鏈接:

常用參數

靜態庫和動態庫的制作(開發重點)

靜態庫的制作過程

動態庫的制作過程


上一篇復習了聯合體和枚舉,這一篇開始講解一下內存管理和gcc工具鏈。

說明:我們學過單片機的一般都是有C語言基礎的了,網上關于C語言的資料有很多,大家如果對C語言不熟悉的話可以先去詳細學一下,再以這篇博文作為復習資料學習。

這篇博文的目的是復習C語言,我們會陸續以30多個編程題作為復習要點,這30多個編程題基本涵蓋了C語言所有的內容了,只要你掌握了這30多個編程題,那么你的C語言基本就沒什么問題了。

注意:由于本專欄是嵌入式全棧開發專欄,為了我們能熟悉以后實際工作中的開發環境,我們寫C語言全部在Linux中的vim編輯器中寫,這么做事為了我們能夠熟練掌握Linux系統的常用命令以及Linux上的vim編輯器的常用工作命令,以達到對口訓練的目的!

vim編輯器的一些工作命令在上一篇博文中已經詳細介紹過了,如果不了解可以先去看看。

我們正式開始:

內存管理

C語言不能直接操作物理內存,程序中使用的內存都是虛擬內存(一個進程再啟動的時候,系統都會給它分配4個G的虛擬內存,一般情況下是按1:3來分配的,1個G給系統內核來使用,3個G給應用層來使用)。

內存分配

3個G的內存又分為:

注:

以上表格有的時候會分為5段,就是把數據段分為數據段和BSS段,即已初始化數據段

和未初始化數據段。

有的時候將以上表格分為3段,就是將堆和棧分到一起,稱為堆棧。

靜態數據區也在數據段,比如static修飾的變量;

代碼段存放的是編譯好的二進制文件;

例如:

//全局變量
int num; //未初始化數據段,BSS段
char ch=’x’; //已初始化數據段int main()
{char*s=”helloworld”;// s存放在棧空間,”helloworld”屬于只讀數據段,不能被修改s[0]=’x’;//這樣寫是不行的,”helloworld”屬于只讀數據段,不能被修改static int a=0;//靜態數據區char *p=(char*)malloc(sizeof(char)*128);//p棧空間,申請的128個字節屬于堆空間char p1[ ]=”helloworld”; //p1是局部變量在棧空間,”helloworld”放在p1里面的,所以”helloworld”就是在棧空間char *p2=”helloworld”; //p2屬于棧空間,占8個字節,它指向了只讀數據區的”helloworld”return 0;
}

堆和棧的區別?(面試重點)

  1. 堆空間是用戶管理的,用戶申請,用戶釋放;而棧空間是系統管理的,當用戶定義一個變量的時候,系統會自動為它開辟一個空間,當一段程序運行完時候,系統會自動釋放掉這個空間。
  2. 堆空間更大,棧空間更小,如果我們要申請連續的大內存,比如說10萬個整數,我們可以去堆空間申請。
  3. 堆空間使用效率低(因為空間大,內存記在一個鏈表里面,申請內存時,它需要去查一下鏈表,查一下哪邊可以使用),棧空間使用效率高(一直往前申請就可以了)。
  4. 堆空間函數結束不會釋放(需要用戶手動釋放),棧空間函數結束自動釋放。

申請內存的函數

malloc

函數原型:

void *malloc(size_t size)

realloc?

函數原型:

void *realloc(void *ptr, size_t size)

如果你用malloc申請128個字節不夠用了,可以通過realloc從128個字節后面即第129個字節開始再申請一些空間,但是前提是后面夠用。

如果第128個字節后面不夠用了,它會在其他的地址給你申請一個空間,將前面128個字節的內容拷貝進去,然后再在后面給你申請一塊空間,返回一個新地址給你使用。

所以realloc相當于是拓展內存的。

free

動態申請的內存需要手動釋放,如果不釋放,會造成內存泄漏。釋放后的指針應該置為空指針,否則會變成野指針。

gcc工具鏈

這一節我們來詳細講一節關于編譯的事情。

一般我們在Linux終端想要編譯我們寫好的.c文件的話,直接就是輸入“gcc 文件名.c -o 文件名”就行,但其實這一個過程是分為4個步驟進行的:

編譯的過程(面試重點)

第一步,預處理:

處理所有以#開頭的代碼,包括頭文件、宏定義、條件編譯

比如:gcc -E hello.c -o hello.i

注:.i就是預處理后的文件。

頭文件預處理過程就是將頭文件直接展開。意思就是它會到操作系統里面把stdio.h這文件給找出來,然后將這個文件的內容復制一份粘貼出來,這就是將頭文件展開的操作。

頭文件的”<>”尖括號就是表示到系統指定的目錄下面去找。

這是頭文件的預處理過程。

宏定義比如#define PRICE 10 ???int sum=PRICE*100;預處理的話直接就是將PRICE替換成int sum=10*100

條件編譯的預處理過程就是直接把#if 0....#endif框選的代碼丟掉。

如果你寫了一段代碼后不需要它了,就可以這樣:

#if 0

Void f1()

{

Printf(“helloworld\n”);

}

#endif

這種操作類似于/* ?*/注釋掉代碼。

第二步,編譯:

語法檢查以及將C語言變成匯編語言

比如:gcc -S hello.i -o hello.s

注:編譯后的文件是.s文件,也就是匯編文件。

第三步,匯編:

將匯編語言變成二進制文件

比如:gcc -c hello.s -o hello.o

注:.o文件就是二進制文件。

以ELF開頭,就是二進制文件:

我們可以用file來看一下

第四步,鏈接:

鏈接代碼需要用到的其他文件(庫文件等)

比如:gcc hello.o -o hello

上一步得到的.o文件還是不能夠直接執行,是因為它還差一步。比如我們剛剛寫的這個代碼用到了printf,當程序從main()函數開始執行到printf這里時,它不知道printf是什么東西,我們還差一步鏈接的操作,即把“printf這個代碼在哪”這個信息鏈接到原文件里面去。

鏈接有兩種,一個是靜態鏈接,一個是動態鏈接(我們直接寫的“gcc 文件名.c -o 文件名”就是一種動態的鏈接)。

動態鏈接就是將“printf這個代碼在哪”這個信息鏈接到原文件里面去,等到運行的時候它會根據我們提示的位置信息就找到printf()這個函數,這樣才能執行。如果libc文件丟了則不能執行了。

比如gcc hello.o -o hello-動態

靜態鏈接生成的二進制文件比動態鏈接的文件大。因為靜態鏈接時是直接將libc中的printf()函數的實現放到生成的二進制文件中。但是,這種方式在libc文件丟失的情況下還是可以執行。

比如gcc hello.o -o hello-靜態 -static

常用參數

-c:只是編譯不鏈接,生成目標文件“.o”

-S:只是編譯不匯編,生成匯編代碼

-E:只進行預編譯,不做其他處理

-g:在可執行程序中包含標準調試信息,用gdb調試程序的時候用到。

-o file:把輸出文件輸出到file里

-V:打印出編譯器內部編譯各過程的命令行信息和編譯器的版本

-I dir:大寫的i,在頭文件的搜索路徑列表中添加dir目錄,如果我們寫的頭文件和.c文件不是在同一個文件中,編譯的時候可以將頭文件放在-I后面。

-L dir:在庫文件的搜索路徑列表中添加dir目錄,鏈接靜態庫和動態庫的時候用到。

-static: 鏈接靜態庫

-l library :連接名為library的庫文件

靜態庫和動態庫的制作(開發重點)

靜態編譯用到靜態庫,動態編譯用到動態庫;

靜態庫的制作過程

什么是靜態庫?怎樣制作靜態庫?

1、寫一個hello.c文件,里面調用了f1()和f2()兩個函數,然后f1()和f2()的實現分別寫在單獨的文件f1.c和f2.c中。

hello.c

f1.c

f2.c

?

2、接下來首先第一步是將f1.c和f2.c兩個原文件轉換成二進制文件。輸入”gcc -c f1.c f2.c”這樣就會自動生成兩個.o文件。

?

3、然后我們用“ar -crv lib(靜態庫的名字隨便取).a f1.o f2.o”,注意一定是以lib開頭,加上靜態庫的名字,.a是靜態庫的后綴,比如“ar -crv libx.a f1.o f2.o”x就是靜態庫的名字。最終生成的libx.a文件就是靜態庫。

?

4、當我們拿到這個靜態庫的時候,要執行hello.c文件就要結合這個靜態庫才行,比如“gcc hello.c -o hello -static -L . -l x”。

注:“.”表示在當前目錄下面。-static是靜態鏈接,-L 后面接庫文件的路徑,-l后面是庫文件的名字。

這樣它就生成了hello的二進制文件

?

5、接下來我們改一下hello.c文件,在main()函數的上方聲明一下f1和f2這兩個函數。

聲明之后我們就可以正常編譯hello.c文件了。

動態庫的制作過程

什么是動態庫?怎樣制作動態庫?

1、同上,寫好f1.c和f2.c和hello.c文件之后,輸入“gcc -fPIC -shared -o lib庫的名字.so f1.c f2.c”,比如gcc -fPIC -shared -o libxx.so f1.c f2.c,最終生成的libxx.so就是動態庫。

?

2、我們編譯hello.c文件之前先鏈接動態庫,“gcc hello.c -o hello -L . -l xx”。

?

3、鏈接好之后用ldd?加上”gcc hello.c -o hello -L . -l xx”這一步操作后生成的二進制文件名來看看它會默認去取哪里找,比如我們看到它會去/lib這個目錄下面去查找,我們將libxx.so動態庫拷貝到/lib目錄下。

注:不同的操作系統可能會去不同的目錄下去找,ldd?加上”gcc hello.c -o hello -L . -l xx”這一步操作后生成的二進制文件名可以查找二進制文件所用到的庫在哪。

拷貝進去/lib中

這個時候我們再執行hello就成功了

以上就是這篇內容,如想了解更多,歡迎訂閱本專欄!

如有問題可評論區或者私信留言,如果想要進交流群請私信!

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

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

相關文章

【Spring Boot】使用 Redis + Cafeine 實現二級緩存

使用 Redis Caffeine 實現二級緩存可以有效提升應用的性能和緩存的命中率。Caffeine 是一個高效的 Java 本地緩存庫&#xff0c;而 Redis 是一個分布式緩存解決方案。通過將兩者結合&#xff0c;Caffeine 作為一級緩存用于快速訪問常用數據&#xff0c;Redis 作為二級緩存用于…

解決LabVIEW通過OPC Server讀取PLC地址時的錯誤180121602

在使用LabVIEW通過OPC Server讀取PLC地址時&#xff0c;若遇到錯誤代碼180121602&#xff0c;建議檢查網絡連接、OPC Server和PLC配置、用戶權限及LabVIEW設置。確保網絡暢通&#xff0c;正確配置OPC變量&#xff0c;取消緩沖設置以實時讀取數據&#xff0c;并使用診斷工具驗證…

簡述vue常用指令

Vue.js 提供了許多內置指令&#xff0c;這些指令用于在模板中添加特殊功能。以下是一些 Vue 的常用內置指令的簡要說明&#xff1a; v-text&#xff1a; 更新元素的 textContent。示例&#xff1a;<span v-text"message"></span> v-html&#xff1a; 更…

2 使用香橙派AIpro報錯 No module named ‘acllite utils‘

當使用jupyter運行香橙派的notebooks下面的案例的時候啟動使用jupyter lab 然后自動跳轉到jupyter頁面。如下圖: 這是自動跳轉過來的。然后運行下面的包的導入后報錯: 報錯為No module named ‘acllite utils’,那么我們打開notebooks文件夾下面的start_notebooks.sh文件:…

【C++練級之路】【Lv.21】C++11——列表初始化和聲明

快樂的流暢&#xff1a;個人主頁 個人專欄&#xff1a;《算法神殿》《數據結構世界》《進擊的C》 遠方有一堆篝火&#xff0c;在為久候之人燃燒&#xff01; 文章目錄 引言一、列表初始化1.1 內置類型1.2 結構體或類1.3 容器 二、聲明2.1 auto2.2 decltype2.3 nullptr 三、STL的…

A*算法搜索的路徑是最優的么?

A * 算法&#xff08;A* Search Algorithm&#xff09;是一種啟發式搜索算法&#xff0c;它旨在找到從起點到終點的最短路徑。在滿足以下條件時&#xff0c;A*算法能夠保證找到最優路徑&#xff1a; 啟發式函數的一致性&#xff08;Consistency&#xff09;或可采納性&#xf…

從“反超”到“引領”,中國衛浴品牌憑何遙遙領先?

作者 | 曾響鈴 文 | 響鈴說 前不久&#xff0c;第28屆中國國際廚房、衛浴設施展覽會(以下簡稱“中國國際廚衛展”)在上海如期舉行&#xff0c;就結果來說真的讓人大開眼界。 沖水聲比蚊子聲更小的馬桶、能化身無感交互平臺的魔鏡柜、可以語音交互的淋浴器&#xff0c;這些“…

Keli5燒寫STM32程序時出現ST-LINK USB communication error錯誤(USB 通信錯誤)

1錯誤原圖 2錯誤原因 前提驅動安裝正確 原因1 usb接觸不良&#xff08;極少出現&#xff09; 解決方法 更換USB線 還不行連下載器一起更換 原因2&#xff08;出現概率比較大&#xff09; 下載器的固件出現問題或下載器固件版本與Keli5的版本不匹配 解決方法 在Keli5的…

[音視頻]ffmepg常用命令

ffmpeg 在音視頻的世界里&#xff0c;ffmpeg可是如雷貫耳的存在&#xff0c;學習音視頻開發&#xff0c;ffmpeg是必須掌握的技能 常用命令 保存m3u8文件 ffmpeg -i http://xxxxx/test.m3u8 -c copy result.mp4

今日早報 每日精選15條新聞簡報 每天一分鐘 知曉天下事 5月26日,星期日

每天一分鐘&#xff0c;知曉天下事&#xff01; 2024年5月26日 星期日 農歷四月十九 1、 醫保局&#xff1a;支持將符合條件的村衛生室納入醫保定點&#xff0c;方便農村居民就醫。 2、 網傳養老金儲備嚴重不足&#xff1f;央視辟謠&#xff1a;這筆錢二十多年來從未動用過&a…

搭建企業級AI應用的流程

搭建企業級AI應用的流程是一個復雜且系統化的工程&#xff0c;它需要從多個維度出發&#xff0c;確保最終的應用既符合企業的業務需求&#xff0c;也具備高效、穩定和可擴展的特性。以下是詳細的步驟&#xff1a; 初步接觸與需求分析是整個項目的基礎。在這一階段&#xff0c;我…

【C++題解】1698. 請輸出帶有特殊尾數的數

問題&#xff1a;1698. 請輸出帶有特殊尾數的數 類型&#xff1a; 題目描述&#xff1a; 請輸出1~n 中所有個位為 1、3、5、7中任意一個數的整數&#xff0c;每行 1 個。( n<1000 ) 比如&#xff0c;假設從鍵盤讀入 20&#xff0c;輸出結果如下&#xff1a; 1 3 5 7 11 1…

LLMs之PEFT之Llama-2:《LoRA Learns Less and Forgets LessLoRA學得更少但遺忘得也更少》翻譯與解讀

LLMs之PEFT之Llama-2&#xff1a;《LoRA Learns Less and Forgets LessLoRA學得更少但遺忘得也更少》翻譯與解讀 導讀&#xff1a;該論文比較了LoRA與完全微調在代碼與數學兩個領域的表現。 背景問題&#xff1a;微調大規模語言模型需要非常大的GPU內存。LoRA這一參數高效微調方…

OpenStack平臺Keystone組件的使用

1. 規劃節點 安裝基礎服務的服務器規劃 IP地址 主機名 節點 192.168.100.10 controller Openstack控制節點 2. 基礎準備 使用機電云共享的單節點的openstack系統&#xff0c;自行修改虛擬網絡編輯器、網絡適配器&#xff0c;系統用戶名&#xff1a;root&#xff0c;密…

【Basic】Upload-Labs-Linux

文章目錄 前言Pass-01Pass-02Pass-03Pass-04Pass-05Pass-06Pass-07Pass-08Pass-09Pass-10Pass-11Pass-12Pass-13Pass-14Pass-15Pass-16解題感悟 前言 美好的一天從刷題開始 Pass-01 我淦20道題&#xff1f;&#xff1f;&#xff1f;一道一道來吧 先看第一道題 先在home里搞一…

原生標簽WebComponent

文章目錄 介紹一、web Component二、怎么使用三、在Vue中使用使用場景 前端必備工具推薦網站(免費圖床、API和ChatAI等實用工具): http://luckycola.com.cn/ 介紹 平常瀏覽各個網站過程中&#xff0c;經常遇到的一種現象&#xff1a;頁面廣告。 這種廣告按照來源可分為兩種&…

蜜罐技術是一種什么防御技術?實現原理是什么?

前言&#xff1a;蜜罐技術的出現改變了這種被動態勢&#xff0c;它通過吸引、誘騙攻擊者&#xff0c;研究學習攻擊者的攻擊目的和攻擊手段&#xff0c;從而延緩乃至阻止攻擊破壞行為的發生&#xff0c;有效保護真實服務資源。 自網絡誕生以來&#xff0c;攻擊威脅事件層出不窮…

簡述Vue 2.0 響應式數據的原理

Vue 2.0 響應式數據的原理主要基于以下幾個關鍵點&#xff1a; 數據劫持與Object.defineProperty&#xff1a; Vue 2.0 使用 Object.defineProperty 方法來劫持對象的屬性&#xff0c;為其添加 getter 和 setter 方法。當數據被訪問或修改時&#xff0c;這些 getter 和 setter …

類和對象【六】友元和內部類

文章目錄 友元友元的作用友元的缺點友元函數語法&#xff1a;特點&#xff1a; 友元類語法&#xff1a;特點&#xff1a; 內部類概念特點 友元 友元的作用 友元提供了一種打破封裝的方式&#xff0c;有時提供了便利。 友元的主要作用就是打破封裝 即可以讓一個類的友元函數…

爬蟲100個Python例子優化

今天看到一個Python 100例的在線資源,感覺每個都需要去點,太費時間了,于是,使用Python將數據爬取下來,方便查看。實際效果如下: 。。。。。。 用了13分鐘,當然,這是優化后的效果,如果沒有優化,需要的時間更長。 爬取url如下: https://www.runoob.com/python/pytho…