GCC編譯器背後的故事
GCC編譯器背後的故事
一、用GCC生成.a靜態庫和.so動態庫
1、建立一個 test2 資料夾,並在該資料夾中建立三個子程式 hello.h、hello.c 和 main.c(這裡還需要下vim)
解決後,在vim中輸入我們建立的三個字程式程式碼
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
#include <stdio.h>
#include "hello.h"
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
如下(程式main.c為例)
2、後將hello.h編譯成.o檔案,但是這裡需要安裝gcc
(安裝過程同上面vim差不多,有點多這裡就不放出來了)
3、由 .o檔案建立靜態庫,並在程式中使用
a…o檔案建立靜態庫
b. 在程式中使用靜態庫
方法一
gcc -o hello main.c -L. -lmyhello
方法二
gcc main.c libmyhello.a -o hello
方法二
gcc -o main.c # 先生成 main.o
gcc -o hello main.o libmyhello.a
然後./hello,執行程式
我們可嘗試刪除 libmyhello靜態庫,再次執行 hello 程式(看程式執行時,是否需要該靜態庫)
結果:靜態庫在程式編譯時會被連線到目的碼中,程式執行時將不再需要該靜態庫。
4、由 .o檔案建立動態庫,並在程式中使用
a. .o檔案建立動態庫
b. 在程式中使用動態庫
方法一
gcc -o hello main.c -L. -lmyhello
方法二
gcc main.c libmyhello.so -o hello
(原因:程式在執行時, 會在/usr/lib 和/lib 等目錄中查詢需要的動態庫檔案。若找到,則載入動態庫,否則將提示類似上述錯誤而終止程式執行)
解決方法:將檔案 libmyhello.so 移動到目錄/usr/lib 中
二、靜態庫與動態庫生成執行檔案大小比較
1、建立一個 test3資料夾,並在該資料夾中分別建立子程式 sub1.h、sub1.c、sub2.h、sub2.c、main.c
mkdir test3
cd test3
vim sub1.h
vim sub1.c
vim sub2.h
vim sub2.c
vim main.c
然後在vim輸入他們的程式程式碼,同上
#ifndef SUB1_H
#define SUB1_H
float x2x(int a, int b);
#endif //SUB1_H
#include"sub1.h"
float x2x(int a,int b)
{
return a+b;
}
#ifndef SUB2_H
#define SUB2_H
float x2y(int a, int b);
#endif //SUB2_H
#include"sub2.h"
float x2y(int a,int b)
{
return a*b;
}
#include<stdio.h>
#include"sub1.h"
#include"sub2.h"
int main(){
int a=2,b=3;
printf("%d + %d = %f\n", a, b, x2x(a, b));
printf("%d × %d = %f\n", a, b, x2y(a, b));
return 0;
}
以第一個為例,輸入過程如下
2、用靜態庫檔案進行連結,生成可執行檔案
a. 將 sub1.c、sub2.c 編譯成 .o檔案
b. .o檔案建立靜態庫
c. 在程式中使用靜態庫
3、用動態庫檔案進行連結,生成可執行檔案
a. .o檔案建立動態庫
b. 在程式中使用動態庫
(在這之前,顯示了一次錯誤,說找不到目錄,然後再試了一遍,就可以了)
d. 兩個可執行檔案大小的比較
gcc -static main.c libsub1.a libsub2.a -o main1 # 重新由靜態庫生成
size main1
ldd main1
size main2
ldd main2
三、gcc編譯器是怎麼編譯的
1、建立一個 test0 資料夾,並在該資料夾中建立一個 hello.c 程式
程式碼如下
#include<stdio.h>
int main (void)
{
printf("Hello World!\n");
return 0;
}
2、程式的編譯過程
a. 預編譯(將原始檔 hello.c 檔案預處理生成 hello.i)
b. 編譯(將預處理生成的 hello.i 檔案編譯生成彙編程式 hello.s)
c. 彙編(將編譯生成的 hello.s 檔案彙編生成目標檔案 hello.o)
d. 連結(分為靜態連結和動態連結,生成可執行檔案)
如下圖
e. 用 size 檢視檔案大小,ldd連結了那些動態庫
3、ELF 檔案的分析
(1) .text:已編譯程式的指令程式碼段
(2) .rodata:ro 代表 read only,即只讀資料(譬如常數 const)
(3) .data:已初始化的 C 程式全域性變數和靜態區域性變數
(4) .bss:未初始化的 C 程式全域性變數和靜態區域性變數
(5) .debug:除錯符號表,偵錯程式用此段的資訊幫助除錯
b. 反彙編 ELF
objdump -S 將其反彙編並且將其 C 語言原始碼混合顯示出來:
4、在ubuntu中下載安裝nasm,對示例彙編程式碼“hello.asm”編譯生成可執行程式,並與上述用C程式碼的編譯生成的可執行程式大小進行對比
a. 安裝nasm編譯器
下載 NSAM 軟體包:連結: link.
輸入sudo apt install nasm
輸入nasm -version
b. 編譯彙編 hello.asm檔案,並於C程式碼的編譯生成的程式大小進行對比
hello.asm 內容如下:
編譯
nasm -f elf64 hello.asm
連結
ld -s -o hello hello.o
c. 彙編與C程式碼的編譯生成的可執行程式大小對比
四、瞭解實際程式是如何藉助第三方庫函式完成程式碼設計
(一)、以遊客身份體驗一下即將絕跡的遠古時代的BBS
在win10下,開啟控制皮膚——>程式——>啟用或關閉Windows功能,啟動"telnet client" 和"適用於Linux的Windows子系統"如圖
b. 開啟一個 cmd命令列視窗,輸入如下命令: telnet bbs.newsmth.net
2、Linux 環境下C語言編譯實現貪吃蛇遊戲
a. 瞭解Linux 系統中終端程式最常用的游標庫(curses)
initscr(): initscr() 是一般 curses 程式必須先呼叫的函式, 一但這個函式被呼叫之後, 系統將根據終端機的形態並啟動 curses 模式
endwin(): curses 通常以呼叫 endwin() 來結束程式. endwin() 可用來關閉curses 模式, 或是暫時的跳離 curses 模式
refresh(): refresh() 為 curses 最常呼叫的一個函式
move(y,x): 將遊標移動至 x,y 的位置
echochar(ch)/addch(ch): 顯示某個字元
b. Ubuntu18.04 安裝curses庫
可通過 whereis 命令標頭檔案和庫檔案都被安裝到哪些目錄中:
c. Linux 環境下C語言編譯實現貪吃蛇遊戲
mkdir testSnake
cd testSnake
vim mysnake.c
gcc mysnake.c -lcurse -o mysnake
./mtsnake
./mysnake 執行該程式,效果如下:
五、參考連結
連結: link.
相關文章
- 嵌入式—編譯器背後的故事編譯
- 編譯器背後的故事(入門練習)編譯
- gcc 編譯器與 clang 編譯器GC編譯
- GCC編譯器的使用GC編譯
- FreeBSD中的GNU C編譯器--編譯器GCC(轉)編譯GC
- 安裝 GCC 編譯器(轉)GC編譯
- gcc編譯GC編譯
- 編譯器GCC與Clang的異同編譯GC
- Linux gcc編譯器安裝LinuxGC編譯
- 開源編譯器 GCC 跨越 5.0,釋出 GCC 5.1編譯GC
- 探索gcc編譯最佳化細節 編譯器最佳化gcc -o3GC編譯
- gcc編譯器小知識FAQ(轉)GC編譯
- Redis持久化背後的故事Redis持久化
- Java main方法背後的故事?JavaAI
- Mac OS X 背後的故事Mac
- HTML5背後的故事HTML
- GCC編譯選項GC編譯
- GCC 編譯選項GC編譯
- 瀏覽器新版本上線背後的故事瀏覽器
- linux下的gcc編譯LinuxGC編譯
- redhat 6.5 gcc編譯器初識之一RedhatGC編譯
- GCC 中的編譯器堆疊保護技術GC編譯
- dyld背後的故事&原始碼分析原始碼
- 蘋果自動駕駛背後的故事蘋果自動駕駛
- 愛回收IPO背後的新老故事
- RestCloud ETL 社群版背後的故事RESTCloud
- 微博春晚背後的技術故事
- Android增量編譯3~5秒的背後Android編譯
- gcc編譯cpp檔案GC編譯
- GNU 編譯器家族 GCC 內部探密(轉)編譯GC
- 誰來背鍋?自動駕駛車禍背後的故事自動駕駛
- 10個社交網站背後的故事網站
- Linux上安裝GCC編譯器過程(轉)LinuxGC編譯
- Linux中gcc編譯工具LinuxGC編譯
- gcc 編譯多個原始檔GC編譯
- gcc最佳編譯引數(轉)GC編譯
- linux 改變GCC編譯器的位元組對齊方式LinuxGC編譯
- 記錄一次gcc的編譯GC編譯