簡單了解一下c編譯過程

2021-09-09 01:12:06 字數 3949 閱讀 2955

大一的時候,學習c

語言,用的是

vc6.0

。用了1

年多,到後來了解了

linux

,知道了

gcc編譯器,開始使用

gcc hello.c -o a.out 

這樣的命令進行編譯。後來又學了

gcc的一些其他的命令,不同的命令可以編譯出不同的目標**。現在想想類似於

vc這種

ide雖然方便,但是對於具體是怎樣的乙個過程就不得而知了。作為乙個優秀的程式設計師怎麼可以不了解這個過程呢。

gcc/g++ 在執行編譯工作的時候,總共4步

1.預處理,生成

.i的檔案  (預處理器

cpp)

2.將預處理後的檔案轉換成組合語言,生成檔案

.s檔案  

()3.從彙編變為目標**

(機器**)生成

.o(.obj)

的檔案  

(彙編器

as)4.連線目標**,生成可執行程式  

(聯結器

ld)我們現在先寫乙個hello world

1 #include 2

#define woeld "world"

3static

int a=0;4

intmain()

5

先預處理一下,可以使用cpp

命令,或者是使用

gcc 的-e

選項gcc -e hello.c > hello.i

乙個簡單的hello world

都要800

多行。

可以看到這些都是函式的宣告。而函式的定義是在鏈結庫中。我們可以認為是寫了好多函式了。然後在main中呼叫。這個跟一般的函式是乙個道理的。只是這些函式是又編譯器幫你寫了。這個就不得不提到,

c語言只是定義了標準庫函式的輸入和輸出,至於實現的過程,是沒有規定的。這個由編譯器廠商自己設計,這就是為什麼有人說

linux

下gcc

編譯後的程式會比

windows下vs

編譯後的程式執行效率上有些區別的乙個原因吧。

像上面的printf

下面這個是vc6.0對

printf

函式的定義

1

int__cdecl printf (

2const

char *format,

3...4)

5/*6* stdout 'print', 'f'ormatted7*/

8

view code

gnu也有個對

printf

函式的定義,下面這個是

glibc-2.2.5

對printf

的定義

1

int2 printf (const

char *format, ...)311

/*the function itself.

*/12

int13 vfprintf (file *s, const char_t *format, va_list ap)148

void outstring(const

char *str)

9

test.c

1 #include "

mylib.h

"2 #include 3

int main(void)4

2.編譯

mylib.c

生成目標檔案

gcc -c mylib.c -o mylib.o

3.將目標檔案加入到靜態庫中

ar rcs libmylib.a mylib.o

4.將靜態庫複製到

linux

的庫目錄

(/usr/lib

或/lib)

下,而mingw

是放在mingw32/lib/gcc/***/4.8.1/ 

中。gcc test.c -o test.exe -lmylib#這裡的

mylib

是 libmylib.a字尾a

和字首lib

都不用寫

如果不想放在庫目錄可以通過-l

引數進行指定。

gcc test.c -o test.exe -lmylib -l .#(這裡的點表示當前目錄

)連線生成後的test.exe 

目錄下就可以不用有

libmylib.a

這個檔案了。

建立動態庫

1.生成目標檔案,然後生成動態庫,要加編譯器選項

-fpic

和鏈結器選項

-shared

gcc -fpic -c mylib.c -o mylib.o#生成中間目標檔案

gcc -shared -o libmylib.so mylib.o#生成動態庫

也可以使用一步完成

gcc -fpic -shared mylib.c -o libmylib.so

2.使用動態鏈結庫

在編譯程式時,使用動態鏈結庫和靜態庫是一致的,使用」-l

庫名」的方式,在生成可執行檔案的時候會鏈結庫檔案。

gcc -o test.exe test.c -l ./ -lmylib

-l指定動態鏈結庫的路勁,

-lmylib

鏈結庫函式

mylib

。-lmylib

是動態庫的呼叫規則。

linux

系統下的動態庫命名方式是

lib*.so,

而在鏈結時表示位

-l*,*

是自己命名的庫名。

但是程式會提示錯誤。

這是因為程式執行時沒有找到動態鏈結庫造成的。程式編譯時鏈結動態庫和執行時使用動態鏈結庫的概念是不同的,在執行時,程式鏈結的動態鏈結庫需要在系統目錄下才行。

使用以下方法可以解決此問題

a. 在

linux

下最方便的解決方案是拷貝

libmylib.so

到絕對目錄 

/lib 下(

但是,要是超級使用者才可以

)。就可以生成可執行程式了

b.第二種方法是:將動態鏈結庫的目錄放到程式搜尋路徑中,可以將庫的路徑加到環境變數

ld_library_path

中實現(

一般放在當前目錄

)3.再次使用動態鏈結庫

動態庫的分為隱式呼叫和顯式呼叫(

上面那種

)兩種呼叫方法:

隱式呼叫的使用使用方法和靜態庫的呼叫差不多,具體方法如下:

gcc -c -i . test.c

gcc -o main.exe -l . test.o libmylib.so

此時把main.exe

移動到其他目錄就會出現這個情況。

(可以把

libmylib.so

移動到系統的

lib目錄就不會出現丟失

so檔案的問題

而test.exe這個通過靜態庫的就沒有這個問題。

使用的環境是mingw32+gcc 4.8.1

參考資料:

TDengine簡單了解一下

tdengine是taosdata的產品,taosdata是由陶姓海歸創立的,目測是用自己的姓氏命名的。tdengine號稱是專為物料網設計的平台,在我看來就是乙個時序資料庫而已,就像influxdb,它也和influxdb進行對比,讀寫速度,儲存空間各方面效能都強於influxdb。tdengin...

swagger重啟 簡單了解一下 Swagger

一 swagger 1 什麼是 swagger swagger 是乙個規範和完整的框架,用於生成 描述 呼叫以及視覺化的 restful 風格的 web 服務。2 為什麼使用 swagger?前後端分離開發時,為了方便前後端介面呼叫規範,需要提供乙個介面文件,但是維護這個介面文件是乙個及其繁瑣的事情...

了解一下NTLM

ntlm 在客戶機與伺服器之間提供身份認證的安全包。ntlm 身份驗證協議 是 質詢 應答身份驗證協議,是windows nt 4.0 及其早期版本中用於網路身份驗證的預設協議。windows 2000 中仍然支援該協議,但它不再是預設的。ntlm身份驗證過程 ntlm 是用於 windows nt...