ubuntu下C编程,编译基础( 转)
buntu下C編程,編譯基礎(chǔ)??
?
C 編程中相關(guān)文件后綴
| .a | 靜態(tài)庫(kù) (archive) |
| .c | C源代碼(需要編譯預(yù)處理) |
| .h | C源代碼頭文件 |
| .i | C源代碼(不需編譯預(yù)處理) |
| .o | 對(duì)象文件 |
| .s | 匯編語(yǔ)言代碼 |
| .so | 動(dòng)態(tài)庫(kù) |
單個(gè)源文件生成可執(zhí)行程序
下面是一個(gè)簡(jiǎn)單的“hello, ubuntu”程序的源代碼:
/* helloubuntu.c */#include <stdio.h>
int main(int argc,char *argv[])
{
printf(“hello, ubuntu\n”);
?
return 0;
}
最簡(jiǎn)單直接的編譯該代碼為可執(zhí)行程序的方法是,將該代碼保存為文件 helloubuntu.c,并執(zhí)行以下命令:
$ gcc -Wall helloubuntu.c編譯器通過(guò)檢查命令行中指定的文件的后綴名可識(shí)別其為 C 源代碼文件。GCC 默認(rèn)的動(dòng)作:編譯源代碼文件生成對(duì)象文件(object file),鏈接對(duì)象文件得到可執(zhí)行程序,刪除對(duì)象文件。由于命令行中未指定可執(zhí)行程序的文件名,編譯器采用默認(rèn)的 a.out。在命令行中輸入程序名可使其執(zhí)行并顯示結(jié)果:
$ ./a.outhello, ubuntu
選項(xiàng) -o 用來(lái)指定所生成的可執(zhí)行程序的文件名。下面的命令生成名為 helloubuntu 的可執(zhí)行程序:
$ gcc -Wall helloubuntu.c -o helloubuntu在命令行中輸入程序名將使其執(zhí)行,如下:
$ ./helloubuntuhello, ubuntu
源文件生成對(duì)象文件
選項(xiàng) -c 指示 GCC 編譯源代碼文件,但將對(duì)象文件保留在磁盤(pán)中并跳過(guò)鏈接對(duì)象文件生成可執(zhí)行文件這一步。在這種情況下,默認(rèn)的輸出文件的文件名同源代碼文件名一致,只不過(guò)后綴換為 .o 。例如:下面的命令將生成名為 helloubuntu.o 的對(duì)象文件:T
$ gcc -c -Wall helloubuntu.c選項(xiàng) -o 可用來(lái)指定生成的對(duì)象文件的文件名。以下命令將產(chǎn)生名為kubuntu.o的對(duì)象文件:
$ gcc -c -Wall helloubuntu.c -o kubuntu.o當(dāng)構(gòu)建對(duì)象庫(kù)或者生成一系列對(duì)象文件以備稍后鏈接用時(shí),一條命令即可從多個(gè)源碼文件生成對(duì)應(yīng)的對(duì)象文件。下面的命令將生成對(duì)象文件ubuntu.o, kubuntu.o 與 xubuntu.o:
$ gcc -c -Wall ubuntu.c kubuntu.c xubuntu.c多個(gè)源文件生成可執(zhí)行程序
即使多個(gè)源碼文件被編譯,GCC編譯器也會(huì)自動(dòng)進(jìn)行鏈接操作。例如:下面的代碼保存在名為 hellomain.c 的文件中并調(diào)用一個(gè)名為 sayhello()的函數(shù): /* hellomain.c */void sayhello(void);
int main(int argc,char *argv[])
{
sayhello();
return 0;
} 以下代碼保存在名為 sayhello.c 的文件中并定義了 sayhello() 函數(shù): /* sayhello.c */
#include <stdio.h>
void sayhello()
{
printf(“hello, ubuntu\n”);
}
下面的命令將兩個(gè)文件分別編譯為對(duì)象文件且將其鏈接為可執(zhí)行程序 hello,并刪除對(duì)象文件:
$ gcc -Wall hellomain.c sayhello.c -o hello編譯預(yù)處理
選項(xiàng) -E 指示編譯器只進(jìn)行編譯預(yù)處理。下面的命令將預(yù)處理源碼文件 helloubuntu.c 并將結(jié)果在標(biāo)準(zhǔn)輸出中列出:
$ gcc -E helloubuntu.c選項(xiàng) -o 用來(lái)將預(yù)處理過(guò)的代碼定向到一個(gè)文件。像本文一開(kāi)始給出的后綴列表所給出的,不需經(jīng)過(guò)預(yù)處理的C源碼文件保存為后綴為 .i的文件中,這種文件可以這樣來(lái)獲得:
$ gcc -E helloubuntu.c -o helloubuntu.i生成匯編代碼
選項(xiàng) -S 指示編譯器生成匯編語(yǔ)言代碼然后結(jié)束。下面的命令將由 C 源碼文件 helloubuntu.c 生成匯編語(yǔ)言文件 helloubuntu.s:
$ gcc -S helloubuntu.c匯編語(yǔ)言的形式依賴(lài)于編譯器的目標(biāo)平臺(tái)。如果多個(gè)源碼文件被編譯,每個(gè)文件將分別產(chǎn)生對(duì)應(yīng)的匯編代碼模塊。
創(chuàng)建靜態(tài)庫(kù)
靜態(tài)庫(kù)是編譯器生成的普通的 .o 文件的集合。鏈接一個(gè)程序時(shí)用庫(kù)中的對(duì)象文件還是目錄中的對(duì)象文件都是一樣的。靜態(tài)庫(kù)的另一個(gè)名字叫歸檔文件(archive),管理這種歸檔文件的工具叫 ar 。
要構(gòu)建一個(gè)庫(kù),首先要編譯出庫(kù)中需要的對(duì)象模塊。例如,下面的兩個(gè)源碼文件為 hellofirst.c 和 hellosecond.c:
/* hellofirst.c */#include <stdio.h>
void hellofirst()
{
printf(“The first hello\n”);
}
/* hellosecond.c */
#include <stdio.h>
void hellosecond()
{
printf(“The second hello\n”);
}
這兩個(gè)源碼文件可以用以下命令編譯成對(duì)象文件:
$ gcc -c -Wall hellofirst.c hellosecond.c程序 ar 配合參數(shù) -r 可以創(chuàng)建一個(gè)新庫(kù)并將對(duì)象文件插入。如果庫(kù)不存在的話(huà),參數(shù) -r 將創(chuàng)建一個(gè)新的,并將對(duì)象模塊添加(如有必要,通過(guò)替換)到歸檔文件中。下面的命令將創(chuàng)建一個(gè)包含本例中兩個(gè)對(duì)象模塊的名為 libhello.a 的靜態(tài)庫(kù):
$ ar -r libhello.a hellofirst.o hellosecond.o 現(xiàn)在庫(kù)已經(jīng)構(gòu)建完成可以使用了。下面的程序 twohellos.c 將調(diào)用該庫(kù)中的這兩個(gè)函數(shù): /* twohellos.c */void hellofirst(void);
void hellosecond(void);
int main(int argc,char *argv[])
{
hellofirst();
hellosecond();
return 0;
}
程序 twohellos 可以通過(guò)在命令行中指定庫(kù)用一條命令來(lái)編譯和鏈接,命令如下:
$ gcc -Wall twohellos.c libhello.a -o twohellos靜態(tài)庫(kù)的命名慣例是名字以三個(gè)字母 lib 開(kāi)頭并以后綴 .a 結(jié)束。所有的系統(tǒng)庫(kù)都采用這種命名慣例,并且它允許通過(guò) -l(ell) 選項(xiàng)來(lái)簡(jiǎn)寫(xiě)命令行中的庫(kù)名。下面的命令與先前命令的區(qū)別僅在于 gcc 期望的找尋該庫(kù)的位置不同:
$ gcc -Wall twohellos.c -lhello -o twohellos指定完整的路徑名可使編譯器在給定的目錄中尋找?guī)臁?kù)名可以指定為絕對(duì)路徑(比如 /usr/worklibs/libhello.a)或者相對(duì)與當(dāng)前目錄的路徑(比如 ./lib/libhello.a)。選項(xiàng) -l 不能具有指定路徑的能力,但是它要求編譯器在系統(tǒng)庫(kù)目錄下找尋該庫(kù)。
創(chuàng)建共享庫(kù)
共享庫(kù)是編譯器以一種特殊的方式生成的對(duì)象文件的集合。對(duì)象文件模塊中所有地址(變量引用或函數(shù)調(diào)用)都是相對(duì)而不是絕對(duì)的,這使得共享模塊可以在程序的運(yùn)行過(guò)程中被動(dòng)態(tài)地調(diào)用和執(zhí)行。
要構(gòu)建一個(gè)共享庫(kù),首先要編譯出庫(kù)中需要的對(duì)象模塊。例如:下面是文件名為 shellofirst.c 和 shellosecond.c 的兩個(gè)源碼文件: /* shellofirst.c */#include <stdio.h>
void shellofirst()
{
printf(“The first hello from a shared library\n”);
}
/* shellosecond.c */
#include <stdio.h>
void shellosecond()
{
printf(“The second hello from a shared library\n”);
}
要將以上兩個(gè)源碼文件編譯成對(duì)象文件,可以用下面的命令:
$ gcc -c -Wall -fpic shellofirst.c shellosecond.c選項(xiàng) -c 告訴編譯器只生成 .o 的對(duì)象文件。選項(xiàng) -fpic 使生成的對(duì)象模塊采用浮動(dòng)的(可重定位的)地址。縮微詞 pic 代表“位置無(wú)關(guān)代碼”(position independent code)。
下面的 gcc 命令將對(duì)象文件構(gòu)建成一個(gè)名為 hello.so 的共享庫(kù):
$ gcc -Wall -shared shellofirst.o shellosecond.o -o hello.so選項(xiàng) -o 用來(lái)為輸出文件命名,而文件后綴名 .so 告訴編譯器將對(duì)象文件鏈接成一個(gè)共享庫(kù)。通常情況下,鏈接器定位并使用 main() 函數(shù)作為程序的入口,但是本例中輸出模塊中沒(méi)有這種入口點(diǎn),為抑制錯(cuò)誤選項(xiàng) -shared 是必須的。
編譯器能將后綴為 .c 的文件識(shí)別為 C 語(yǔ)言源代碼文件,并知道如何將其編譯成為對(duì)象文件。基于這一點(diǎn),先前的兩條命令我們可以合并為一條;下面的命令直接將模塊編譯并存儲(chǔ)為共享庫(kù):
$ gcc -Wall -fpic -shared shellofirst.c shellosecond.c -o hello.so 下面的程序,存儲(chǔ)在文件 stwohellos.c 內(nèi),是調(diào)用共享庫(kù)中兩個(gè)函數(shù)的主程序: /* stwohellos.c */void shellofirst(void);
void shellosecond(void);
int main(int argc,char *argv[])
{
shellofirst();
shellosecond();
return 0;
}
該程序可以用下面的命令編譯并鏈接共享庫(kù):
$ gcc -Wall stwohellos.c hello.so -o stwohellos程序 stwohello 已經(jīng)完成,但要運(yùn)行它必須讓其能定位到共享庫(kù) hello.so,因?yàn)閹?kù)中的函數(shù)要在程序運(yùn)行時(shí)被加載。
超越命名慣例
如果環(huán)境要求你使用 .c 以外的后綴名來(lái)命名你的 C 源碼文件,你可以通過(guò) -x 選項(xiàng)來(lái)指定其對(duì)應(yīng)的語(yǔ)言以忽略我們的命名規(guī)范。例如,下面的命令將從文件 helloworrld.jxj 編譯 C 語(yǔ)言源代碼并生成可執(zhí)行文件 helloubuntu:
$ gcc -xc helloubuntu.jxj -o helloubuntu通常,在沒(méi)有 -x 選項(xiàng)的情況下,任何具有未知后綴名的源碼文件名都被認(rèn)為是連接器可以識(shí)別的選項(xiàng),并在不做任何更改的情況下傳遞給鏈接器。選項(xiàng) -x 對(duì)其后的所有未知后綴的文件都起作用。例如,下面的命令使 gcc 將 align.zzz 和 types.xxx 都作為 C 源碼文件來(lái)處理:
$ gcc -c -xc align.zzz types.xxx轉(zhuǎn)載于:https://www.cnblogs.com/yaopan007/p/3481891.html
總結(jié)
以上是生活随笔為你收集整理的ubuntu下C编程,编译基础( 转)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 一个切图仔的 CSS 笔记
- 下一篇: 求助:安装程序无法创建一个DCOM用户帐