C程序編譯步驟詳解_第1頁(yè)
C程序編譯步驟詳解_第2頁(yè)
C程序編譯步驟詳解_第3頁(yè)
C程序編譯步驟詳解_第4頁(yè)
C程序編譯步驟詳解_第5頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、C/C+程序編譯步驟詳解新一篇:MakefileC/C+語(yǔ)言很多人都比較熟悉,這基本上是每位大學(xué)生必學(xué)的一門(mén)編程語(yǔ)言,通常還都是作為程序設(shè)計(jì)入門(mén)語(yǔ)言學(xué)的,并且課程大多安排在大一。剛上大學(xué),孩子們還都很乖,學(xué)習(xí)也比較認(rèn)真,用心。所以,C/C+語(yǔ)言掌握地也都不錯(cuò),不用說(shuō)編譯程序,就是寫(xiě)個(gè)上幾百行的程序都不在話下,但是他們真的知道C/C +程序編譯的步驟么?我想很多人都不甚清楚,如果他接下來(lái)學(xué)過(guò)“編譯原理”,也許能說(shuō)個(gè)大概。VC的“舒適”開(kāi)發(fā)環(huán)境屏蔽了很多編譯的細(xì)節(jié),這無(wú)疑降低了初學(xué)者的入門(mén)門(mén)檻,但是也“剝奪”了他們“知其所以然”的權(quán)利,致使很多東西只能死記硬背,遇到相關(guān)問(wèn)題就“丈二”。實(shí)際上,我也

2、是在學(xué)習(xí)Linux環(huán)境下編程的過(guò)程中才逐漸弄清楚C/C+源代碼是如何一步步變成可執(zhí)行文件的??傮w來(lái)說(shuō),C/C+源代碼要經(jīng)過(guò):預(yù)處理、編譯、匯編和連接四步才能變成相應(yīng)平臺(tái)下的可執(zhí)行文件。大多數(shù)時(shí)候,程序員通過(guò)一個(gè)命令就能完成上述四個(gè)步驟。比如下面這段C的“Hello world!”代碼:File: hw.c#include int main(int argc, char *argv) printf(Hello World!n); return 0;如果用gcc編譯,只需要一個(gè)命令就可以生成可執(zhí)行文件hw:xiaosuogentux hw $ gcc -o hw hw.cxiaosuogentux

3、 hw $ ./hw Hello World!我們可以用-v參數(shù)來(lái)看看gcc到底在背后都做了些什么動(dòng)作:Reading specs from /usr/lib/gcc/i686-pc-linux-gnu/specsConfigured with: /var/tmp/portage/sys-devel/gcc-3.4.6-r2/work/gcc-3.4.6/configure -prefix=/usr -bindir=/usr/i686-pc-linux-gnu/gcc-bin/3.4.6 -includedir=/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/incl

4、ude -datadir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.6 -mandir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.6/man -infodir=/usr/share/gcc-data/i686-pc-linux-gnu/3.4.6/info -with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/include/g+-v3 -host=i686-pc-linux-gnu -build=i686-pc-linux-gnu -disabl

5、e-altivec -enable-nls -without-included-gettext -with-system-zlib -disable-checking -disable-werror -enable-secureplt -disable-libunwind-exceptions -disable-multilib -disable-libgcj -enable-languages=c,c+,f77 -enable-shared -enable-threads=posix -enable-_cxa_atexit -enable-clocale=gnuThread model: p

6、osixgcc version 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10)/usr/libexec/gcc/i686-pc-linux-gnu/3.4.6/cc1 -quiet -v hw.c -quiet -dumpbase hw.c -mtune=pentiumpro -auxbase hw -version -o /tmp/ccYB6UwR.signoring nonexistent directory /usr/local/includeignoring nonexistent directory /usr/lib/gcc/i6

7、86-pc-linux-gnu/3.4.6/././././i686-pc-linux-gnu/include#include . search starts here:#include search starts here:/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/include/usr/includeEnd of search list.GNU C version 3.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10) (i686-pc-linux-gnu) compiled by GNU C version 3

8、.4.6 (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.9).GGC heuristics: -param ggc-min-expand=81 -param ggc-min-heapsize=97004/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/././././i686-pc-linux-gnu/bin/as -V -Qy -o /tmp/ccq8uGED.o /tmp/ccYB6UwR.sGNU assembler version 2.17 (i686-pc-linux-gnu) using BFD version 2.17/

9、usr/libexec/gcc/i686-pc-linux-gnu/3.4.6/collect2 -eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o hw /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/./././crt1.o /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/./././crti.o /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/crtbegin.o -L/usr/lib/gcc/i686-pc-linux-gnu/3.4

10、.6 -L/usr/lib/gcc/i686-pc-linux-gnu/3.4.6 -L/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/././././i686-pc-linux-gnu/lib -L/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/././. /tmp/ccq8uGED.o -lgcc -as-needed -lgcc_s -no-as-needed -lc -lgcc -as-needed -lgcc_s -no-as-needed /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/crtend.o

11、/usr/lib/gcc/i686-pc-linux-gnu/3.4.6/./././crtn.o稍微整理一下,去掉一些冗余信息后,如下:cc1 hw.c -o /tmp/ccYB6UwR.sas -o /tmp/ccq8uGED.o /tmp/ccYB6UwR.sld -o hw /tmp/ccq8uGED.o以上三個(gè)命令分別對(duì)應(yīng)于編譯步驟中的預(yù)處理+編譯、匯編和連接。預(yù)處理和編譯還是放在了一個(gè)命令(cc1)中進(jìn)行的,可以把它再次拆分為以下兩步:cpp -o hw.i hw.ccc1 hw.i -o /tmp/ccYB6UwR.s一個(gè)精簡(jiǎn)過(guò)的能編譯以上hw.c文件的Makefile如下:.P

12、HONY: cleanall: hwhw: hw.o ld -dynamic-linker /lib/ld-linux.so.2 -o hw /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/crtbegin.o hw.o -lc /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/crtend.o /usr/lib/crtn.ohw.o: hw.s as -o hw.o hw.shw.s: hw.i /usr/libexec/gcc/i686-pc-linux-gnu/3.4.6/c

13、c1 -o hw.s hw.chw.i: hw.c cpp -o hw.i hw.cclean: rm -rf hw.i hw.s hw.o當(dāng)然,上面Makefile中的一些路徑是我系統(tǒng)上的具體情況,你的可能與我的不同。接下來(lái)我們按照編譯順序看看編譯器每一步都做了什么。首先是預(yù)處理,預(yù)處理后的文件hw.i:# 1 hw.c# 1 # 1 ._extension_ typedef _quad_t _off64_t;_extension_ typedef int _pid_t;_extension_ typedef struct int _val2; _fsid_t;.extern int rem

14、ove (_const char *_filename) _attribute_ (_nothrow_);extern int rename (_const char *_old, _const char *_new) _attribute_ (_nothrow_);.int main(int argc, char *argv)printf(Hello World!n);return 0;注:由于文件比較大,所以只留下了少部分具有代表性的內(nèi)容??梢钥匆?jiàn)預(yù)處理器把所有要包含(include)的文件(包括遞歸包含的文件)的內(nèi)容都添加到了原始的C源文件中,然后把其輸出到輸出文件,除此之外,它還展開(kāi)了

15、所有的宏定義,所以在預(yù)處理器的輸出文件中你將找不到任何宏。這也提供了一個(gè)查看宏展開(kāi)結(jié)果的簡(jiǎn)便方法。第二步“編譯”,就是把C/C+代碼“翻譯”成匯編代碼:.file hw.c .section .rodata.LC0: .string Hello World!n .text.globl main .type main, functionmain: pushl %ebp movl %esp, %ebp subl $8, %esp andl $-16, %esp movl $0, %eax addl $15, %eax addl $15, %eax shrl $4, %eax sall $4, %e

16、ax subl %eax, %esp subl $12, %esp pushl $.LC0 call printf addl $16, %esp movl $0, %eax leave ret .size main, .-main .section .note.GNU-stack,progbits .ident GCC: (GNU) (Gentoo 3.4.6-r2, ssp-3.4.6-1.0, pie-8.7.10)這個(gè)匯編文件比預(yù)處理后的C/C+文件小了很多,去除了很多不必要的東西,比如說(shuō)沒(méi)用到的類(lèi)型聲明和函數(shù)聲明等。第三步“匯編”,將第二步輸出的匯編代碼翻譯成符合一定格式的機(jī)器代碼,在

17、Linux上一般表現(xiàn)為ELF目標(biāo)文件。xiaosuogentux hw $ file hw.ohw.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped最后一步“連接”,將上步生成的目標(biāo)文件和系統(tǒng)庫(kù)的目標(biāo)文件和庫(kù)文件連接起來(lái),最終生成了可以在特定平臺(tái)運(yùn)行的可執(zhí)行文件。為什么還要連接系統(tǒng)庫(kù)中的某些目標(biāo)文件(crt1.o, crti.o等)呢?這些目標(biāo)文件都是用來(lái)初始化或者回收C運(yùn)行時(shí)環(huán)境的,比如說(shuō)堆內(nèi)存分配上下文環(huán)境的初始化等,實(shí)際上crt也正是C RunTime的縮寫(xiě)。這也暗示了另外一點(diǎn):程序并不是

18、從main函數(shù)開(kāi)始執(zhí)行的,而是從crt中的某個(gè)入口開(kāi)始的,在Linux上此入口是 _start。以上Makefile生成的是動(dòng)態(tài)連接的可執(zhí)行文件,如果要生成靜態(tài)連接的可執(zhí)行文件需要將Makefile中的相應(yīng)段修改:hw: hw.o ld -m elf_i386 -static -o hw /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/gcc/i686-pc-linux-gnu/3.4.6/crtbeginT.o -L/usr/lib/gcc/i686-pc-linux-gnu/3.4.6 -L/usr/i686-pc-linux-gnu/lib -L/usr/lib/ hw.o -start-group -lgcc -lgcc_eh -lc -end-group

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論