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

Linux 下編譯C程序

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

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

1. 編譯單個(gè)源文件

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

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

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

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

在默認(rèn)情況下產(chǎn)生的可執(zhí)行程序名為a.out,但你通常可以通過(guò) gcc
的"-o"選項(xiàng)來(lái)指定自己的可執(zhí)行程序名稱(chēng)。

2. 編譯多個(gè)源文件

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

#include <stdio.h>

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

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

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

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

#include <stdlib.h>

void goodbye_world(void):

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

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

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

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

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

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

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

#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"選項(xiàng),它告訴 GCC
查看系統(tǒng)提供的數(shù)學(xué)庫(kù)(libm)。因?yàn)長(zhǎng)inux和UNIX的系統(tǒng)函數(shù)庫(kù)通常以"lib"為前綴,所以我們假設(shè)它存在。真正的函數(shù)庫(kù)位置隨系統(tǒng)的不同而
不同,但它一般會(huì)位于目錄/lib或/usr/lib中,在這些目錄中還有數(shù)以百計(jì)的其他必需的系統(tǒng)函數(shù)庫(kù)。

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

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

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

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

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

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

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

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

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

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

#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)

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

需要設(shè)置一個(gè)環(huán)境變量LD_LIBRARY_PATH來(lái)制定額外的共享函數(shù)庫(kù)搜索路徑,
# 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)
運(yùn)行程序
# ./goodbye
Goodbye, world!

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

Linux 下編譯C程序


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

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

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 久久久亚洲精品视频 | 免费超级淫片日本高清视频 | 综合色区 | 婷婷久久综合网 | 久九精品 | 久久婷婷五夜综合色频 | 婷婷色视频 | 99热久久这里就有精品 | 久久综合九色欧美综合狠狠 | 涩涩色中文综合亚洲 | 久久精品啪啪嗷嗷叫 | 九九热免费在线观看 | 色偷偷成人网免费视频男人的天堂 | 青草青草久热精品视频在线观看 | 夜夜嘿视频免费看 | 四虎最新在线 | 91热爆在线 | 午夜精品福利在线 | 日本三级带日本三级带黄首页 | 国产亚洲第一伦理第一区 | 亚洲精品成人在线 | 亚洲阿v天堂在线观看2017 | 精品国精品国产自在久国产不卡 | 一区二区福利视频 | 欧美天天 | 亚洲视频在线a视频 | 日本一本在线观看 | 国产精品分类视频分类一区 | 久久国产在线观看 | 久草不卡视频 | 久久午夜一区二区 | 尤物福利 | 久久中文娱乐网 | 99热久久精里都是精品6 | 成 人 黄 色 视频播放1 | 激情五月色婷婷丁香伊人 | a成人毛片免费观看 | 亚洲精品久久一区二区无卡 | 91精品久久久久久久久网影视 | 中文一级国产特级毛片视频 | 99久久99热久久 |