大一的時候,學習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先預處理一下,可以使用cpp#define woeld "world"
3static
int a=0;4
intmain()
5
命令,或者是使用
gcc 的-e
選項gcc -e hello.c > hello.i
乙個簡單的hello world
都要800
多行。
可以看到這些都是函式的宣告。而函式的定義是在鏈結庫中。我們可以認為是寫了好多函式了。然後在main中呼叫。這個跟一般的函式是乙個道理的。只是這些函式是又編譯器幫你寫了。這個就不得不提到,
c語言只是定義了標準庫函式的輸入和輸出,至於實現的過程,是沒有規定的。這個由編譯器廠商自己設計,這就是為什麼有人說
linux
下gcc
編譯後的程式會比
windows下vs
編譯後的程式執行效率上有些區別的乙個原因吧。
像上面的printf
下面這個是vc6.0對
printf
函式的定義
1view codeint__cdecl printf (
2const
char *format,
3...4)
5/*6* stdout 'print', 'f'ormatted7*/
8
gnu也有個對
printf
函式的定義,下面這個是
glibc-2.2.5
對printf
的定義
1test.cint2 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
1 #include "2.編譯mylib.h
"2 #include 3
int main(void)4
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...