亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Linux 下編譯C程序

系統(tǒng) 2146 0
GCC 已不再是主要針對GNU項目自身的軟件的小型 C
語言編譯器了。如今,它已支持了許多不同的語言,包括
C、C++、Ada、Fortran、Objective C,甚至還有Java。事實上,現(xiàn)代 Linux
系統(tǒng)除了可以自豪地炫耀那些由 GNU
工具直接支持的語言以外,它還支持大量其他語言。日益流行的腳本語言
Perl、Python 和 Ruby,以及正在不斷發(fā)展的mono
可移植C#實現(xiàn)的確有助于沖淡人們對 Linux
編程的傳統(tǒng)看法,但這完全是另外一個問題了。

Linux 內(nèi)核和許多其他自由軟件以及開放源碼應(yīng)用程序都是用 C 語言編寫并使用
GCC 編譯的。

1. 編譯單個源文件

為了進(jìn)行測試,你可以創(chuàng)建"Hello World"程序:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
printf("Hello world!\n");
exit(0);
}

使用如下命令編譯并測試這個代碼:
# gcc -o hello hello.c
# ./hello
Hello wordl!

在默認(rèn)情況下產(chǎn)生的可執(zhí)行程序名為a.out,但你通??梢酝ㄟ^ gcc
的"-o"選項來指定自己的可執(zhí)行程序名稱。

2. 編譯多個源文件

源文件message.c包含一個簡單的消息打印函數(shù):

#include <stdio.h>

void goodbye_world(void)
{
printf("Goodbye, world!\n");
}

使用gcc的"-c"標(biāo)記來編譯支持庫代碼:
# gcc -c message.c

這一過程的輸出結(jié)果是一個名為message.o的文件,它包含適合連接到一個較大程序的已編譯目標(biāo)代碼。

創(chuàng)建一個簡單的示例程序,它包含一個調(diào)用goodbye_world的main函數(shù)

#include <stdlib.h>

void goodbye_world(void):

int main(int argc, char **argv)
{
goodbye_world();
exit(0);
}

使用GCC編譯這個程序:
# gcc -c main.c

現(xiàn)在有了兩個目標(biāo)文件: message.o 和 main.o 。它們包含能夠被 Linux
執(zhí)行的目標(biāo)代碼。要從這個目標(biāo)代碼創(chuàng)建Linux可執(zhí)行程序,需要再一次調(diào)用 GCC
來執(zhí)行連接階段的工作:
# gcc -o goodbye message.o main.o

運行編譯結(jié)果:
# ./goodbye
Goodbye, world!

前面這些單獨的步驟也可以簡化為一個命令,這是因為 GCC
對如何將多個源文件編譯為一個可執(zhí)行程序有內(nèi)置的規(guī)則。
# gcc -o goodbye message.c main.c
# ./goodbye
Goodbye, world!

3. 使用外部函數(shù)庫

GCC 常常與包含標(biāo)準(zhǔn)例程的外部軟件庫結(jié)合使用,幾乎每一個 Linux
應(yīng)用程序都依賴于由 GNU C 函數(shù)庫 GLIBC。
應(yīng)用外部函數(shù)庫的例子:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define MAX_INPUT 25

int main(int agrc, char **argv)
{
char input[MAX_INPUT];
double angle;

printf("Give me an angle (in radians) ==>");
if(!fgets(input, MAX_INPUT, stdin)){
perror("an error occurred.\n");
}
angle = strtod(input, NULL);

printf("sin(%e) = %e\n", angle, sin(angle));

return 0;
}

編譯命令:
# gcc -o trig -lm trig.c

GCC 的"-lm"選項,它告訴 GCC
查看系統(tǒng)提供的數(shù)學(xué)庫(libm)。因為Linux和UNIX的系統(tǒng)函數(shù)庫通常以"lib"為前綴,所以我們假設(shè)它存在。真正的函數(shù)庫位置隨系統(tǒng)的不同而
不同,但它一般會位于目錄/lib或/usr/lib中,在這些目錄中還有數(shù)以百計的其他必需的系統(tǒng)函數(shù)庫。

4. 共享函數(shù)庫與靜態(tài)函數(shù)庫

Linux系統(tǒng)上的函數(shù)庫分為兩種不同的類型:共享的和靜態(tài)的

靜態(tài)函數(shù)庫:每次當(dāng)應(yīng)用程序和靜態(tài)連接的函數(shù)庫一起編譯時,任何引用的庫函數(shù)中的代碼都會被直接包含進(jìn)最終的二進(jìn)制程序。

共享函數(shù)庫:包含每個庫函數(shù)的單一全局版本,它在所有應(yīng)用程序之間共享。這一過程背后所涉及的機制相當(dāng)復(fù)雜,但主要依靠的是現(xiàn)代計算機的虛擬內(nèi)存能力,它允許包含庫函數(shù)的物理內(nèi)存安全地在多個獨立用戶程序之間共享。

使用共享函數(shù)庫不僅減少了文件的容量和 Linux
應(yīng)用程序在內(nèi)存中覆蓋的區(qū)域,而且它還提高了系統(tǒng)的安全性。一個被許多不同程序同時調(diào)用的共享函數(shù)庫很可能會駐留在內(nèi)存中,以在需要使用它時被立即使用,
而不是位于磁盤的交換分區(qū)中。這有助于進(jìn)一步減少一些大型 Linux
應(yīng)用程序的裝載時間。

將上面的 message.c 作為共享庫函數(shù)使用的例子:

# gcc -fPIC -c message.c
"PIC"命令行標(biāo)記告訴 GCC
產(chǎn)生的代碼不要包含對函數(shù)和變量具體內(nèi)存位置的引用,這是因為現(xiàn)在還無法知道使用該消息代碼的應(yīng)用程序會將它連接到哪一段內(nèi)存地址空間。這樣編譯輸出的文
件 message.o 可以被用于建立共享函數(shù)庫,我們只需使用gcc的"-shared"標(biāo)記即可:
# gcc -shared -o libmessage.so message.o

將上面的 mian.c使用共享庫函數(shù)ligmessage.so 編譯:
# gcc -o goodbye -lmessage -L. message.o
"-lmessage"標(biāo)記來告訴 GCC 在連接階段引用共享函數(shù)庫 libmessage.so
。"-L."標(biāo)記告訴 GCC 函數(shù)庫可能位于當(dāng)前目錄中,否則 GNU
的連接器會查找標(biāo)準(zhǔn)系統(tǒng)函數(shù)庫目錄,在本例的情況下,就找不到可用的函數(shù)庫了。

此時運行編譯好的goodbye會提示找不到共享函數(shù)庫:
#./goodbye
./goodbye: error while loading shared libraries: libmessage.so: cannot
open shared object file: No such file or directory

可以使用命令 ldd
來發(fā)現(xiàn)一個特定應(yīng)用程序需要使用的函數(shù)庫。ldd搜索標(biāo)準(zhǔn)系統(tǒng)函數(shù)庫路徑并顯示一個特定程序使用的函數(shù)庫版本。

#ldd goodbye
linux-gate.so.1 => (0×00493000)
libmessage.so => not found
libc.so.6 => /lib/libc.so.6 (0×0097c000)
/lib/ld-linux.so.2 (0×0095a000)

庫文件 libmessage.so
不能在任何一個標(biāo)準(zhǔn)搜索路徑中找到,而且系統(tǒng)提供的配置文件 /etc/ld.so.conf
也沒有包含一個額外的條目來指定包含該庫文件的目錄。

需要設(shè)置一個環(huán)境變量LD_LIBRARY_PATH來制定額外的共享函數(shù)庫搜索路徑,
# export LD_LIBRARY_PATH=`pwd`
# ldd goodbye
linux-gate.so.1 => (0x002ce000)
libmessage.so => /tmp/cpro/libmessage.so (0x00b0f000)
libc.so.6 => /lib/libc.so.6 (0x0097c000)
/lib/ld-linux.so.2 (0x0095a000)
運行程序
# ./goodbye
Goodbye, world!

gcc在命令行上經(jīng)常使用的幾個選項是:
-c
只預(yù)處理、編譯和匯編源程序,不進(jìn)行連接。編譯器對每一個源程序產(chǎn)生一個目標(biāo)文件。
-o file 確定輸出文件為file。如果沒有用-o選項,缺省的可執(zhí)行文件的輸出是
a.out,目標(biāo)文件和匯編文件的輸出對source.suffix分別是source.o和source.s,預(yù)處理的C源程序的輸出是標(biāo)準(zhǔn)輸出stdout。
-Dmacro或-Dmacro=defn 其作用類似于源程序里的#define。例如:% gcc -c
-DHAVE_GDBM -DHELP_FILE=\"help\" cdict.c其中第一個-
D選項定義宏HAVE_GDBM,在程序里可以用#ifdef去檢查它是否被設(shè)置。第二個-D選項將宏HELP_FILE定義為字符串"help"(由于
反斜線的作用,引號實際上已成為該宏定義的一部分),這對于控制程序打開哪個文件是很有用的。
-Umacro
某些宏是被編譯程序自動定義的。這些宏通??梢灾付ㄔ谄渲羞M(jìn)行編譯的計算機系統(tǒng)類型的符號,用戶可以在編譯某程序時加上
-v選項以查看gcc缺省定義了哪些宏。如果用戶想取消其中某個宏定義,用-Umacro選項,這相當(dāng)于把#undef
macro放在要編譯的源文件的開頭。
-Idir
將dir目錄加到搜尋頭文件的目錄列表中去,并優(yōu)先于在gcc缺省的搜索目錄。在有多個-I選項的情況下,按命令行上-I選項的前后順序搜索。dir可使用相對路徑,如-I../inc等。
-O
對程序編譯進(jìn)行優(yōu)化,編譯程序試圖減少被編譯程序的長度和執(zhí)行時間,但其編譯速度比不做優(yōu)化慢,而且要求較多的內(nèi)存。
-O2 允許比-O更好的優(yōu)化,編譯速度較慢,但結(jié)果程序的執(zhí)行速度較快。
-g
產(chǎn)生一張用于調(diào)試和排錯的擴展符號表。-g選項使程序可以用GNU的調(diào)試程序GDB進(jìn)行調(diào)試。優(yōu)化和調(diào)試通常不兼容,同時使用-g和-O(-O2)選項經(jīng)常會使程序產(chǎn)生奇怪的運行結(jié)果。所以不要同時使用-g和-O(-O2)選項。
-fpic或-fPIC 產(chǎn)生位置無關(guān)的目標(biāo)代碼,可用于構(gòu)造共享函數(shù)庫。
以上是gcc的編譯選項。gcc的命令行上還可以使用連接選項。事實上,gcc將所有不能識別的選項傳遞給連接程序ld。連接程序ld將幾個目標(biāo)文件和庫
程序組合成一個可執(zhí)行文件,它要解決對外部變量、外部過程、庫程序等的引用。但我們永遠(yuǎn)不必要顯式地調(diào)用ld。利用gcc命令去連接各個文件是很簡單的,
即使在命令行里沒有列出庫程序,gcc也能保證某些庫程序以正確的次序出現(xiàn)。
gcc的常用連接選項有下列幾個:
-Ldir
將dir目錄加到搜尋-l選項指定的函數(shù)庫文件的目錄列表中去,并優(yōu)先于gcc缺省的搜索目錄。在有多個-L選項的情況下,按命令行上-L選項的前后順序搜索。dir可使用相對路徑。如-L../lib等。
-lname
在連接時使用函數(shù)庫libname.a,連接程序在-Ldir選項指定的目錄下和/lib,/usr/lib目錄下尋找該庫文件。在沒有使用-static選項時,如果發(fā)現(xiàn)共享函數(shù)庫libname.so,則使用libname.so進(jìn)行動態(tài)連接。
-static 禁止與共享函數(shù)庫連接。
-shared 盡量與共享函數(shù)庫連接。
這是Linux上連接程序的缺省選項。下面是一個使用gcc進(jìn)行連接的例子:
% gcc -o prog main.o subr.o -L../lib -lany -lm

Linux 下編譯C程序


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!??!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 欧洲精品在线观看 | 91精品国产手机 | 免费视频久久 | 一区二区三区四区视频在线观看 | 欧美一级在线毛片免费观看 | 精品久久久中文字幕一区 | 中国一级免费毛片 | 亚洲精品一区二区三区在线看 | 久久大香香蕉国产免费网站 | 尹人综合 | 五月婷婷综合色 | 日本一区二区三区久久 | 尤物福利 | 久久伊人草 | 台湾佬中文娱乐2222vvv | 在线观看精品一区 | 一级毛片aaa片免费观看 | 乱色美www女麻豆 | 免费a视频在线观看 | 亚洲视频手机在线观看 | 综合亚洲精品一区二区三区 | 香蕉视频一级片 | 色天使久久综合网天天 | 国产精品色婷婷在线观看 | 护士日本xxxxx丰满hd4k | 国产香蕉精品视频在 | 大学生久久香蕉国产线看观看 | 日韩欧美日本 | www.日本色 | 五月婷中文 | 香蕉久久网 | 九九影视理论片在线播放 | 大学生一一级毛片在线播放 | 四虎成年永久免费网站 | 一级毛片高清大全免费观看 | 色婷婷六月桃花综合影院 | 欧美一级精品高清在线观看 | 欧美一级免费 | 中文字幕亚洲区 | 天码毛片一区二区三区入口 | 美日韩视频 |