GCC編譯四步標準

來源:互聯網
上載者:User
標準 ANSI C:這一標準是 ANSI(美國國家標準局)於 1989 年制定的 C 語言標準。後來被 ISO(國際標準組織)接受為標準,因此也稱為 ISO C。 ANSI C 的目標是為各種作業系統上的 C 程式提供可移植性保證,而不僅僅限於 UNIX。 該標準不僅定義了 C 程式設計語言的語發和語義,而且還定義了一個標準庫。這個庫可以根據 標頭檔劃分為 15 個部分,其中包括:字元類型 (<ctype.h>)、錯誤碼 (<errno.h>)、 浮點常數 (<float.h>)、數學常數 (<math.h>)、標準定義 (<stddef.h>)、 標準 I/O (<stdio.h>)、工具函數 (<stdlib.h>)、字串操作 (<string.h>)、 時間和日期 (<time.h>)、可變參數表 (<stdarg.h>)、訊號 (<signal.h>)、 非局部跳轉 (<setjmp.h>)、本地資訊 (<local.h>)、程式斷言 (<assert.h>) 等等。  POSIX:該標準最初由 IEEE 開發的標準族,部分已經被 ISO 接受為國際標準。該標準的具體內容 見 1.1.3。POSIX.1 和 POSIX.2 分別定義了 POSIX 相容作業系統的 C 語言系統介面 以及 shell 和工具標準。這兩個標準是通常提到的標準。  SVID:System V 的介面描述。System V 介面描述(SVID)是描述 AT&&;T Unix System V 操作 系統的文檔,是對 POSIX 標準的擴充超集。  XPG:X/Open 可移植性指南。X/Open 可移植性指南(由 X/Open Company, Ltd.出版), 是比 POSIX 更為一般的標準。X/Open 擁有 Unix 的著作權,而 XPG 則指定成為 Unix 作業系統必須滿足的要求。  ---------------------------------------     GCC是GNU CC的簡稱,它是符合上述ANSI C標準的編譯系統,能夠編譯C、C++、Object C等語言編寫的程式。GCC還是一個交叉平台編譯器,能夠在當前CPU平台為多種不同架構的硬體平台開發軟體,因此適合嵌入式領域的開發編譯。   GCC所支援的尾碼名的解釋 .c C原始程式 .C/.cc/.cxx  C++原始程式 .m  Object C原始程式 .i  已經過預先處理的C原始程式 .ii  已經過預先處理的C++原始程式 .s/.S  組合語言原始程式 .h  預先處理檔案(標頭檔) .o  目標檔案 .a/.so  編譯後的庫檔案       三、詳解GCC編譯流程     使用vi編寫源檔案hello.c。    #include <stdio.h> int main() {         int i;         for(i=1;i<9;i++)                 printf("Hello World %d times!\n",i);         return 0; }       1、預先處理階段     該階段的作用是把預先處理檔案,也就是標頭檔編譯進來。在此例中,就是要把stdio.h編譯進來。可使用-E選項查看,作用是讓gcc在預先處理結束後停止編譯過程。 [armlinux@lqm program]$ gcc -E hello.c -o hello.i [armlinux@lqm program]$ cat hello.i | less   # 1 "hello.c" # 1 "<built-in>" # 1 "<command line>" # 1 "hello.c" # 1 "/usr/include/stdio.h" 1 3 # 28 "/usr/include/stdio.h" 3 # 1 "/usr/include/features.h" 1 3 # 291 "/usr/include/features.h" 3 # 1 "/usr/include/sys/cdefs.h" 1 3 # 292 "/usr/include/features.h" 2 3 # 314 "/usr/include/features.h" 3 # 1 "/usr/include/gnu/stubs.h" 1 3 # 315 "/usr/include/features.h" 2 3 # 29 "/usr/include/stdio.h" 2 3   ...   extern void funlockfile (FILE *__stream) ; # 679 "/usr/include/stdio.h" 3 # 2 "hello.c" 2 int main() {         int i;         for(i=1;i<9;i++)                 printf("Hello World %d times!\n",i);         return 0; }       由此可見,stdio.h的內容已經插入到hello.c中,即GCC完成了預先處理過程。     2、編譯階段     GCC的工作是首先檢查代碼的規範性、是否有語法錯誤,以確定代碼實際要做的工作。檢查無誤後,將之翻譯為組合語言。可用-S來查看,即只編譯而不進入彙編階段。 [armlinux@lqm program]$ gcc -S hello.i -o hello.s [armlinux@lqm program]$ cat hello.s
        .file   "hello.c"         .section        .rodata .LC0:         .string "Hello World %d times!\n"         .text .globl main         .type   main,@function main:         pushl   %ebp         movl    %esp, %ebp         subl    $8, %esp         andl    $-16, %esp         movl    $0, %eax         subl    %eax, %esp         movl    $1, -4(%ebp) .L2:         cmpl    $8, -4(%ebp)         jle     .L5         jmp     .L3 .L5:         subl    $8, %esp         pushl   -4(%ebp)         pushl   $.LC0         call    printf         addl    $16, %esp         leal    -4(%ebp), %eax         incl    (%eax)         jmp     .L2 .L3:         movl    $0, %eax         leave         ret .Lfe1:         .size   main,.Lfe1-main         .ident  "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"       3、彙編階段     GCC把編譯產生的.s檔案轉換為目標檔案.o。這時使用-c選項就可以看到彙編代碼已經轉換成.o的目標代碼了。 [armlinux@lqm program]$ gcc -c hello.s -o hello.o     4、連結階段     成功編譯之後,就進入了連結階段。這裡首先要明白“庫”的概念。這個程式中沒有“printf”的函數實現,且在預先處理階段包含進來的“stdio.h”中只有該函數的聲明,而沒有定義函數的實現。如何?“printf”。答案是:系統把這些函數的實現都做到名位libc.so.6的庫檔案裡了,沒有特別指定時,GCC會到預設的搜尋路徑“/usr/lib”下進行尋找。也就是連結到libc.so.6庫函數中去來實現函數“printf”,這就是連結的作用。     在RedHat 9下的函數庫如下:     /lib:系統必備共用庫     /usr/lib:標準共用庫和靜態庫     /usr/X11R6/lib:X11R6的函數庫     /usr/local/lib:本地函數庫     標頭檔:     /usr/include:系統標頭檔     /usr/local/include:本地標頭檔     在/etc/ld.so.conf中包含著共用庫的搜尋位置。我的libc.so.6在/lib下面,它是一個link,指向libc-2.3.2.so。這是因為我用的C庫--glibc版本是2.3.2。     函數庫一般可分為靜態庫和動態庫兩種。靜態庫是指連結時把庫檔案的代碼全部加到可執行檔中,因此產生的檔案比較大,但是在運行時就不再需要庫檔案了。其尾碼名一般為“.a”。動態庫在連結時並沒有把庫檔案的代碼加入到可執行檔中,而是在程式執行時由運行時連結檔案載入庫,這樣可以節省系統的開銷。動態庫一般尾碼名為“.so”。GCC在編譯時間預設使用動態庫。   [armlinux@lqm program]$ gcc hello.o -o hello1 [armlinux@lqm program]$ ls -l hello1 -rwxrwxr-x    1 armlinux armlinux    11582  8月 28 17:42 hello1 [armlinux@lqm program]$ file hello1 hello1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), not sd [armlinux@lqm program]$ gcc -static hello.o -o hello2 [armlinux@lqm program]$ ls -l hello2 -rwxrwxr-x    1 armlinux armlinux   423442  8月 28 17:43 hello2 [armlinux@lqm program]$ file hello2 hello2: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, statically linked, not stripped [armlinux@lqm program]$ ./hello1 Hello World 1 times! Hello World 2 times! Hello World 3 times! Hello World 4 times! Hello World 5 times! Hello World 6 times! Hello World 7 times! Hello World 8 times! [armlinux@lqm program]$ ./hello2 Hello World 1 times! Hello World 2 times! Hello World 3 times! Hello World 4 times! Hello World 5 times! Hello World 6 times! Hello World 7 times! Hello World 8 times!     hello2是靜態編譯,大小423442,是動態編譯的36.56倍。利用file可以看出此檔案statically linked,還是dynamically linked (uses shared libs)。       至此,GCC的整個編譯連結過程就完成了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.