国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
gcc系列教程
不經(jīng)意間,GCC已發(fā)展到了4.3的版本,盡管在軟件開發(fā)社區(qū)之外乏人聞問,但因為GCC在幾乎所有開源軟件和自由軟件中都會用到,因此它的編譯性能的漲 落會直接影響到Linux 、Firefox乃至于OpenOffice.org和Apache等幾千個項目的開發(fā)。因此,把GCC擺在開源軟件的核心地位是一點也不為過。另一方面,GCC4.3的出現(xiàn),正在牽引著廣大程序員們的心。如果我們非要用一個詞來說明GCC與程序員之間的關(guān)系,那無疑是"心隨心動"。
歷史篇
作為自由軟件的旗艦項目,Richard Stallman 在十多年前剛開始寫作 GCC 的時候,還只是把它當(dāng)作僅僅一個 C程序語言的編譯器;GCC 的意思也只是 GNU C Compiler 而已。經(jīng)過了這么多年 的發(fā)展,GCC 已經(jīng)不僅僅能支持 C語言;它現(xiàn)在還支持Ada 語言、C++ 語言、Java 語言、Objective C 語言、Pascal語言、COBOL語言,以及支持函數(shù)式編程和邏輯編程的 Mercury 語言,等等。而 GCC 也不再單只是 GNU C語言編譯器的意思了,而是變成了 GNU Compiler Collection 也即是 GNU 編譯器家族的意思了。另一方面,說到 GCC對于各種硬件平臺的支持,概括起來就是一句話:無所不在。幾乎所有有點實際用途的硬件平臺,甚至包括有些不那么有實際用途的硬件平臺。
Gcc 簡介
Linux系統(tǒng)下的gcc(GNU CCompiler)是GNU推出的功能強大、性能優(yōu)越的多平臺編譯器,是GNU的代表作品之一。Gcc是可以在多種硬體平臺上編譯出可執(zhí)行程序的超級編譯器,其執(zhí)行效率與一般的編譯器相比平均效率要高20%~30%。
官方網(wǎng)站:
http://gcc.gnu.org/

      gcc是linux的唯一編譯器,沒有g(shù)cc就沒有l(wèi)inux,gcc的重要性就不可言喻啦。居然這么重要,那就很值得我們來好好研究下啦。好啦,開始我們的gcc之旅吧!


首先消除gcc和g++誤區(qū)吧。
gcc和g++都是GNU(組織)的一個編譯器。

誤區(qū)一:gcc只能編譯c代碼,g++只能編譯c++代碼

兩者都可以,但是請注意:
1.后綴為.c的,gcc把它當(dāng)作是C程序,而g++當(dāng)作是c++程序;后綴為.cpp的,兩者都會認(rèn)為是c++程序,注意,雖然c++是c的超集,但是兩者對語法的要求是有區(qū)別的,例如:
#include <stdio.h>
int main(int argc, char* argv[]) {
  if(argv == 0) return;
  printString(argv);
  return;
}
int printString(char* string) {
sprintf(string, "This is a test."n");
}
如果按照C的語法規(guī)則,OK,沒問題,但是,一旦把后綴改為cpp,立刻報三個錯:“printString未定義”;
“cannot convert `char**' to `char*”;
”return-statement with no value“;
分別對應(yīng)前面紅色標(biāo)注的部分。可見C++的語法規(guī)則更加嚴(yán)謹(jǐn)一些。
2.編譯階段,g++會調(diào)用gcc,對于c++代碼,兩者是等價的,但是因為gcc命令不能自動和C++程序使用的庫聯(lián)接,所以通常用g++來完成鏈接,為了統(tǒng)一起見,干脆編譯/鏈接統(tǒng)統(tǒng)用g++了,這就給人一種錯覺,好像cpp程序只能用g++似的。

誤區(qū)二:gcc不會定義__cplusplus宏,而g++會

實際上,這個宏只是標(biāo)志著編譯器將會把代碼按C還是C++語法來解釋,如上所述,如果后綴為.c,并且采用gcc編譯器,則該宏就是未定義的,否則,就是已定義。

誤區(qū)三:編譯只能用gcc,鏈接只能用g++

嚴(yán)格來說,這句話不算錯誤,但是它混淆了概念,應(yīng)該這樣說:編譯可以用gcc/g++,而鏈接可以用g++或者gcc-lstdc++。因為gcc命令不能自動和C++程序使用的庫聯(lián)接,所以通常使用g++來完成聯(lián)接。但在編譯階段,g++會自動調(diào)用gcc,二者等價。

誤區(qū)四:extern "C"與gcc/g++有關(guān)系

實際上并無關(guān)系,無論是gcc還是g++,用extern"c"時,都是以C的命名方式來為symbol命名,否則,都以c++方式命名。試驗如下:
me.h:
extern "C" void CppPrintf(void);

me.cpp:
#include <iostream>
#include "me.h"
using namespace std;
void CppPrintf(void)
{
    cout << "Hello"n";
}

test.cpp:
#include <stdlib.h>
#include <stdio.h>
#include "me.h"       
int main(void)
{
   CppPrintf();
   return 0;
}

1. 先給me.h加上extern "C",看用gcc和g++命名有什么不同

[root@root G++]# g++ -S me.cpp
[root@root G++]# less me.s
.globl _Z9CppPrintfv       //注意此函數(shù)的命名
       .type   CppPrintf,@function
[root@root GCC]# gcc -S me.cpp
[root@root GCC]# less me.s
.globl _Z9CppPrintfv       //注意此函數(shù)的命名
       .type   CppPrintf,@function
完全相同!
             
2. 去掉me.h中extern "C",看用gcc和g++命名有什么不同

[root@root GCC]# gcc -S me.cpp
[root@root GCC]# less me.s
.globl _Z9CppPrintfv       //注意此函數(shù)的命名
       .type  _Z9CppPrintfv, @function
[root@root G++]# g++ -S me.cpp
[root@root G++]# less me.s
.globl _Z9CppPrintfv       //注意此函數(shù)的命名
       .type  _Z9CppPrintfv, @function
完全相同!
【結(jié)論】完全相同,可見extern "C"與采用gcc/g++并無關(guān)系,以上的試驗還間接的印證了前面的說法:在編譯階段,g++是調(diào)用gcc的。

今天,我們繼續(xù)gcc之旅吧。上節(jié)我們講了些gcc的歷史發(fā)展什么的,還有就是gcc與g++的區(qū)別。今天我們就從整體上對gcc編譯過程有個細(xì)致的了解,也好明白他的工作原理,好為以后深入學(xué)習(xí)研究打下個基礎(chǔ)。
gcc的編譯流程分為四個步驟,分別為:
· 預(yù)處理(Pre-Processing)
· 編譯(Compiling)
· 匯編(Assembling)
· 鏈接(Linking

以hello.c為例子,在這四個步驟中可以設(shè)置選項分別生成hello.i, hello.s, hello.o以及最終的hello文件:
   hello.c : 最初的源代碼文件;
   hello.i : 經(jīng)過編譯預(yù)處理的源代碼;
   hello.s : 匯編處理后的匯編代碼;
   hello.o :編譯后的目標(biāo)文件,即含有最終編譯出的機器碼,但它里面所引用的其他文件中函數(shù)的內(nèi)存位置尚未定義。
   hello / a.out : 最終的可執(zhí)行文件
   (還有.a(靜態(tài)庫文件), .so(動態(tài)庫文件), .s(匯編源文件)留待以后討論)

下面就具體來查看一下gcc是如何完成四個步驟的。

hello.c源代碼

#include<stdio.h>
int main()
{
  printf("Hello World!\n");
  return 0;
}

(1)預(yù)處理階段

在該階段,編譯器將上述代碼中的stdio.h編譯進(jìn)來,并且用戶可以使用gcc的選項”-E”進(jìn)行查看,該選項的作用是讓gcc在預(yù)處理結(jié)束后停止編譯過程。

《深入理解計算機系統(tǒng)》中是這么說的:
  預(yù)處理器(cpp)根據(jù)以字符#開頭的命令(directives),修改原始的C程序。如hello.c中#include<stdio.h>指令告訴預(yù)處理器讀系統(tǒng)頭文件stdio.h的內(nèi)容,并把它直接插入到程序文本中去。結(jié)果就得到另外一個C程序,通常是以.i作為文件擴展名的。
 
注意:
       Gcc指令的一般格式為:Gcc [選項] 要編譯的文件[選項] [目標(biāo)文件]
其中,目標(biāo)文件可缺省,Gcc默認(rèn)生成可執(zhí)行的文件名為:編譯文件.out

[gan@localhost gcc]# gcc –E hello.c –o hello.i
選項”-o”是指目標(biāo)文件,”.i”文件為已經(jīng)過預(yù)處理的C原始程序。以下列出了hello.i文件的部分內(nèi)容:

typedef int (*__gconv_trans_fct) (struct__gconv_step *,
        struct __gconv_step_data*, void *,
        __const unsigned char *,
        __const unsigned char**,
        __const unsigned char *,unsigned char **,
        size_t *);

# 2 "hello.c" 2

int main()
{
printf("Hello World!\n");
return 0;
}

由此可見,gcc確實進(jìn)行了預(yù)處理,它把”stdio.h”的內(nèi)容插入到hello.i文件中。

(2)編譯階段

接下來進(jìn)行的是編譯階段,在這個階段中,Gcc首先要檢查代碼的規(guī)范性、是否有語法錯誤等,以確定代碼的實際要做的工作,在檢查無誤后,Gcc把代碼翻譯成匯編語言。用戶可以使用”-S”選項來進(jìn)行查看,該選項只進(jìn)行編譯而不進(jìn)行匯編,生成匯編代碼。匯編語言是非常有用的,它為不同高級語言不同編譯器提供了通用的語言。如:C編譯器和Fortran編譯器產(chǎn)生的輸出文件用的都是一樣的匯編語言。

[gan@localhost gcc]# gcc –S hello.i –o hello.s
以下列出了hello.s的內(nèi)容,可見Gcc已經(jīng)將其轉(zhuǎn)化為匯編了,感興趣的讀者可以分析一下這一行簡單的C語言小程序是如何用匯編代碼實現(xiàn)的。
    .file   "hello.c"
    .section    .rodata
    .align 4

.LC0:
    .string     "Hello World!"
    .text
.globl main
    .type main, @function
main:
    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, %eax
    subl %eax, %esp
    subl $12, %esp
    pushl $.LC0

     call puts
    addl $16, %esp
    movl $0, %eax
    leave
    ret
    .size   main, .-main
    .ident "GCC: (GNU) 4.0.0 20050519 (Red Hat4.0.0-8)"
    .section   .note.GNU-stack,"",@progbits


(3)匯編階段

匯編階段是把編譯階段生成的”.s”文件轉(zhuǎn)成目標(biāo)文件,讀者在此可使用選項”-c”就可看到匯編代碼已轉(zhuǎn)化為”.o”的二進(jìn)制目標(biāo)代碼了。如下所示:
[gan@localhost gcc]# gcc –c hello.s –o hello.o

(4)鏈接階段

在成功編譯之后,就進(jìn)入了鏈接階段。在這里涉及到一個重要的概念:函數(shù)庫。

在這個源程序中并沒有定義”printf”的函數(shù)實現(xiàn),且在預(yù)編譯中包含進(jìn)的”stdio.h”中也只有該函數(shù)的聲明,而沒有定義函數(shù)的實現(xiàn),那么,是在哪里實現(xiàn)”printf”函數(shù)的呢?最后的答案是:系統(tǒng)把這些函數(shù)實現(xiàn)都被做到名為libc.so.6的庫文件中去了,在沒有特別指定時,gcc會到系統(tǒng)默認(rèn)的搜索路徑”/usr/lib”下進(jìn)行查找,也就是鏈接到libc.so.6庫函數(shù)中去,這樣就能實現(xiàn)函數(shù)”printf”了,而這也就是鏈接的作用。

函數(shù)庫一般分為靜態(tài)庫和動態(tài)庫兩種。靜態(tài)庫是指編譯鏈接時,把庫文件的代碼全部加入到可執(zhí)行文件中,因此生成的文件比較大,但在運行時也就不再需要庫文件了。其后綴名一般為”.a”。動態(tài)庫與之相反,在編譯鏈接時并沒有把庫文件的代碼加入到可執(zhí)行文件中,而是在程序執(zhí)行時由運行時鏈接文件加載庫,這樣可以節(jié)省系統(tǒng)的開銷。動態(tài)庫一般后綴名為”.so”,如前面所述的libc.so.6就是動態(tài)庫。gcc在編譯時默認(rèn)使用動態(tài)庫。
(Linux下動態(tài)庫文件的擴展名為".so"(SharedObject)。按照約定,所有動態(tài)庫文件名的形式是libname.so(可能在名字中加入版本號)。這樣,線程函數(shù)庫被稱作libthread.so。靜態(tài)庫的文件名形式是libname.a。共享archive的文件名形式是libname.sa。共享archive只是一種過渡形式,幫助人們從靜態(tài)庫轉(zhuǎn)變到動態(tài)庫。)
完成了鏈接之后,gcc就可以生成可執(zhí)行文件,如下所示。

[gan@localhost gcc]# gcc hello.o –o hello

運行該可執(zhí)行文件,出現(xiàn)正確的結(jié)果如下。
[root@localhost Gcc]# ./hello
Hello World!

這一節(jié),我們來關(guān)注下gcc的常用參數(shù) ,有機會也好多加練習(xí)啦。                             

       首先來看看我們gcc的版本吧,gcc --version這個命令就會顯示gcc的版本號啦。好啦,下面開始下面開始講解gcc的常用參數(shù)啦o(∩_∩)o...
[參數(shù)詳解]

-c  
只激活預(yù)處理,編譯,和匯編,也就是他只把程序做成obj文件
例子用法:
gcc -c hello.c
他將生成.o的obj文件  
-S
只激活預(yù)處理和編譯,就是指把文件編譯成為匯編代碼。
例子用法
gcc -S hello.c
他將生成.s的匯編代碼,你可以用文本編輯器察看
-E
只激活預(yù)處理,這個不生成文件,你需要把它重定向到一個輸出文件里
面.
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧,一個hello word 也要與處理成800行的代碼
-o
制定目標(biāo)名稱,缺省的時候,gcc 編譯出來的文件是a.out,很難聽,如果 你和我有同感,改掉它,哈哈
例子用法
gcc -o hello.exe hello.c (哦,windows用習(xí)慣了)
gcc -o hello.asm -S hello.c
-ansi
關(guān)閉gnu c中與ansi c不兼容的特性,激活ansi c的專有特性(包括禁止一
些asm inline typeof關(guān)鍵字,以及UNIX,vax等預(yù)處理宏,

-Wall
     顯示警告信息
-O0
-O1
-O2
-O3
編譯器的優(yōu)化選項的4個級別,-O0表示沒有優(yōu)化,-O1為缺省值,-O3優(yōu)化級別最
高  

-g
只是編譯器,在編譯的時候,產(chǎn)生調(diào)試信息。

-llibrary  
制定編譯的時候使用的庫
例子用法
gcc -lcurses hello.c
使用ncurses庫編譯程序

-Ldir
制定編譯的時候,搜索庫的路徑。比如你自己的庫,可以用它制定目錄,不然
編譯器將只在標(biāo)準(zhǔn)庫的目錄找。這個dir就是目錄的名稱。   
-gstabs
此選項以stabs格式聲稱調(diào)試信息,但是不包括gdb調(diào)試信息.  
-gstabs+
此選項以stabs格式聲稱調(diào)試信息,并且包含僅供gdb使用的額外調(diào)試信息.

-ggdb
此選項將盡可能的生成gdb的可以使用的調(diào)試信息.
-static   此選項將禁止使用動態(tài)庫,所以,編譯出來的東西,一般都很大,也不需要什么 動態(tài)連接庫,就可以運行.

-share   此選項將盡量使用動態(tài)庫,所以生成文件比較小,但是需要系統(tǒng)由動態(tài)庫.

-traditional   試圖讓編譯器支持傳統(tǒng)的C語言特性

-fno-asm
此選項實現(xiàn)ansi選項的功能的一部分,它禁止將asm,inline和typeof用作
關(guān)鍵字。

-fno-strict-prototype
只對g++起作用,使用這個選項,g++將對不帶參數(shù)的函數(shù),都認(rèn)為是沒有顯式
的對參數(shù)的個數(shù)和類型說明,而不是沒有參數(shù).
而gcc無論是否使用這個參數(shù),都將對沒有帶參數(shù)的函數(shù),認(rèn)為城沒有顯式說
明的類型

-fthis-is-varialble
就是向傳統(tǒng)c++看齊,可以使用this當(dāng)一般變量使用.

-fcond-mismatch
允許條件表達(dá)式的第二和第三參數(shù)類型不匹配,表達(dá)式的值將為void類型

-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
這四個參數(shù)是對char類型進(jìn)行設(shè)置,決定將char類型設(shè)置成unsigned char(前
兩個參數(shù))或者 signed char(后兩個參數(shù))

-include file
包含某個代碼,簡單來說,就是便以某個文件,需要另一個文件的時候,就可以
用它設(shè)定,功能就相當(dāng)于在代碼中使用#include
例子用法:
gcc hello.c -include /root/pianopan.h

-imacros file
將file文件的宏,擴展到gcc/g++的輸入文件,宏定義本身并不出現(xiàn)在輸入文件


-Dmacro
相當(dāng)于C語言中的#define macro

-Dmacro=defn
相當(dāng)于C語言中的#define macro=defn

-Umacro
相當(dāng)于C語言中的#undef macro

-undef
取消對任何非標(biāo)準(zhǔn)宏的定義

-Idir
在你是用#include"file"的時候,gcc/g++會先在當(dāng)前目錄查找你所制定的頭
文件,如果沒有找到,他回到缺省的頭文件目錄找,如果使用-I制定了目錄,他
回先在你所制定的目錄查找,然后再按常規(guī)的順序去找.
對于#include,gcc/g++會到-I制定的目錄查找,查找不到,然后將到系
統(tǒng)的缺省的頭文件目錄查找

-I-
就是取消前一個參數(shù)的功能,所以一般在-Idir之后使用

-idirafter dir
在-I的目錄里面查找失敗,講到這個目錄里面查找.

-iprefix prefix
-iwithprefix dir
一般一起使用,當(dāng)-I的目錄查找失敗,會到prefix+dir下查找

-nostdinc
使編譯器不再系統(tǒng)缺省的頭文件目錄里面找頭文件,一般和-I聯(lián)合使用,明確
限定頭文件的位置

-nostdin C++
規(guī)定不在g++指定的標(biāo)準(zhǔn)路經(jīng)中搜索,但仍在其他路徑中搜索,.此選項在創(chuàng)建
libg++庫使用

-C
在預(yù)處理的時候,不刪除注釋信息,一般和-E使用,有時候分析程序,用這個很
方便的  
-M
生成文件關(guān)聯(lián)的信息。包含目標(biāo)文件所依賴的所有源代碼
你可以用gcc -M hello.c來測試一下,很簡單。  
-MM
和上面的那個一樣,但是它將忽略由#include造成的依賴關(guān)系。  
-MD
和-M相同,但是輸出將導(dǎo)入到.d的文件里面

-MMD
和-MM相同,但是輸出將導(dǎo)入到.d的文件里面

-Wa,option
此選項傳遞option給匯編程序;如果option中間有逗號,就將option分成多個選
項,然后傳遞給會匯編程序

-Wl.option
此選項傳遞option給連接程序;如果option中間有逗號,就將option分成多個選 項,然后傳遞給會連接程序.

-x language filename設(shè)定文件所使用的語言,使后綴名無效,對以后的多個有效.也就是根據(jù)約定C語言的后綴名稱是.c的,而C++的后綴名是.C或者.cpp,如果你很個性,決定你的C代碼文件的后綴名是.pig 哈哈,那你就要用這個參數(shù),這個參數(shù)對他后面的文件名都起作用,除非到了下一個參數(shù)的使用??梢允褂玫膮?shù)嗎有下面的這些   `c', `objective-c', `c-header', `c++', `cpp-output',`assembler', and `assembler-with-cpp'.   看到英文,應(yīng)該可以理解的。   例子用法:   gcc -x chello.pig

-x none filename關(guān)掉上一個選項,也就是讓gcc根據(jù)文件名后綴,自動識別文件類型   例子用法:   gcc -x c hello.pig -x nonehello2.c

-pipe   使用管道代替編譯中臨時文件,在使用非gnu匯編工具的時候,可能有些問題gcc -pipe -o hello.exe hello.c

-funsigned-char -fno-signed-char -fsigned-char-fno-unsigned-char   這四個參數(shù)是對char類型進(jìn)行設(shè)置,決定將char類型設(shè)置成unsigned char(前兩個參數(shù))或者 signed char(后兩個參數(shù))

          GCC的參數(shù)是很多的,這也只是部分。不過對于初學(xué)者來說,一時之間掌握這么多的參數(shù)也是有點困難的,不過一般推薦使用命令:gcc    -Wall hello.c  -o hello就足夠啦。一般要使用-Wall這個參數(shù),他可以列出源程序在編譯過程中出現(xiàn)的錯誤警告等信息,這是很有幫助的,注意:-Wall這個參數(shù)是在編譯過程中使用的,若先把源程序編譯成目標(biāo)文件,則在鏈接過程中不要使用這個參數(shù)。你還可以再加個-v參數(shù):列出比較詳細(xì)的信息,(在標(biāo)準(zhǔn)錯誤)顯示執(zhí)行編譯階段的命令.同時顯示編譯器驅(qū)動程序,預(yù)處理器,編譯器的版本號.
     這些在我們平時使用的過程中應(yīng)該已經(jīng)足夠啦,若還想了解其他的一些參數(shù),可以下載gcc的幫助文檔有時間自己研究下。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
gcc使用手冊
gcc and g++分別是gnu的c & c++編譯器
g++編譯命令選項
gcc編譯的四階段 | 素包子
gcc總結(jié)【基本用法】【選項】【動靜態(tài)庫】
gcc 如何編譯cpp文件啊
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服