gcc and g++分別是gnu的c & c++編譯器

gcc and g++分別是gnu的c & c++編譯器前端

gcc/g++在執行編譯工做的時候,總共須要4步c++

1.預處理,生成.i的文件[預處理器cpp]
2.將預處理後的文件不轉換成彙編語言,生成文件.s[編譯器egcs]
3.有彙編變爲目標代碼(機器代碼)生成.o的文件[彙編器as]
4.鏈接目標代碼,生成可執行程序[連接器ld]objective-c

 

 

[參數詳解]
-x language filename
設定文件所使用的語言,使後綴名無效,對之後的多個有效.也就是根
據約定C語言的後綴名稱是.c的,而C++的後綴名是.C或者.cpp,若是
你很個性,決定你的C代碼文件的後綴名是.pig 哈哈,那你就要用這
個參數,這個參數對他後面的文件名都起做用,除非到了下一個參數
的使用。
可使用的參數嗎有下面的這些
`c', `objective-c', `c-header', `c++', `cpp-output',
`assembler', and `assembler-with-cpp'.
看到英文,應該能夠理解的。
例子用法:
gcc -x c hello.pig

-x none filename
關掉上一個選項,也就是讓gcc根據文件名後綴,自動識別文件類型
例子用法:
gcc -x c hello.pig -x none hello2.c

-c
只激活預處理,編譯,和彙編,也就是他只把程序作成obj文件
例子用法:
gcc -c hello.c
他將生成.o的obj文件編程

-S
只激活預處理和編譯,就是指把文件編譯成爲彙編代碼。
例子用法
gcc -S hello.c
他將生成.s的彙編代碼,你能夠用文本編輯器察看windows

-E
只激活預處理,這個不生成文件,你須要把它重定向到一個輸出文件裏
面.
例子用法:
gcc -E hello.c > pianoapan.txt
gcc -E hello.c | more
慢慢看吧,一個hello word 也要與處理成800行的代碼編輯器

-o
制定目標名稱,缺省的時候,gcc 編譯出來的文件是a.out,很難聽,若是
你和我有同感,改掉它,哈哈
例子用法
gcc -o hello.exe hello.c (哦,windows用習慣了)
gcc -o hello.asm -S hello.cide

-pipe
使用管道代替編譯中臨時文件,在使用非gnu彙編工具的時候,可能有些問

gcc -pipe -o hello.exe hello.c函數

-ansi
關閉gnu c中與ansi c不兼容的特性,激活ansi c的專有特性(包括禁止一
些asm inline typeof關鍵字,以及UNIX,vax等預處理宏,工具

-fno-asm
此選項實現ansi選項的功能的一部分,它禁止將asm,inline和typeof用做
關鍵字。

-fno-strict-prototype
只對g++起做用,使用這個選項,g++將對不帶參數的函數,都認爲是沒有顯式
的對參數的個數和類型說明,而不是沒有參數.
而gcc不管是否使用這個參數,都將對沒有帶參數的函數,認爲城沒有顯式說
明的類型

-fthis-is-varialble
就是向傳統c++看齊,可使用this當通常變量使用.

-fcond-mismatch
容許條件表達式的第二和第三參數類型不匹配,表達式的值將爲void類型

-funsigned-char
-fno-signed-char
-fsigned-char
-fno-unsigned-char
這四個參數是對char類型進行設置,決定將char類型設置成unsigned char(前
兩個參數)或者 signed char(後兩個參數)

-include file
包含某個代碼,簡單來講,就是便以某個文件,須要另外一個文件的時候,就能夠
用它設定,功能就至關於在代碼中使用#include<filename>
例子用法:
gcc hello.c -include /root/pianopan.h

-imacros file
將file文件的宏,擴展到gcc/g++的輸入文件,宏定義自己並不出如今輸入文件


-Dmacro
至關於C語言中的#define macro

-Dmacro=defn
至關於C語言中的#define macro=defn

-Umacro
至關於C語言中的#undef macro測試

-undef
取消對任何非標準宏的定義

-Idir
在你是用#include"file"的時候,gcc/g++會先在當前目錄查找你所制定的頭
文件,若是沒有找到,他回到缺省的頭文件目錄找,若是使用-I制定了目錄,他
回先在你所制定的目錄查找,而後再按常規的順序去找.
對於#include<file>,gcc/g++會到-I制定的目錄查找,查找不到,而後將到系
統的缺省的頭文件目錄查找

-I-
就是取消前一個參數的功能,因此通常在-Idir以後使用

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

-iprefix prefix
-iwithprefix dir
通常一塊兒使用,當-I的目錄查找失敗,會到prefix+dir下查找

-nostdinc
使編譯器再也不繫統缺省的頭文件目錄裏面找頭文件,通常和-I聯合使用,明確
限定頭文件的位置

-nostdin C++
規定不在g++指定的標準路經中搜索,但仍在其餘路徑中搜索,.此選項在建立
libg++庫使用

-C
在預處理的時候,不刪除註釋信息,通常和-E使用,有時候分析程序,用這個很
方便的

-M
生成文件關聯的信息。包含目標文件所依賴的全部源代碼
你能夠用gcc -M hello.c來測試一下,很簡單。

-MM
和上面的那個同樣,可是它將忽略由#include<file>形成的依賴關係。

-MD
和-M相同,可是輸出將導入到.d的文件裏面

-MMD
和-MM相同,可是輸出將導入到.d的文件裏面

-Wa,option
此選項傳遞option給彙編程序;若是option中間有逗號,就將option分紅多個選
項,而後傳遞給會彙編程序

-Wl.option
此選項傳遞option給鏈接程序;若是option中間有逗號,就將option分紅多個選
項,而後傳遞給會鏈接程序.

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

-Ldir
制定編譯的時候,搜索庫的路徑。好比你本身的庫,能夠用它制定目錄,否則
編譯器將只在標準庫的目錄找。這個dir就是目錄的名稱。

-O0
-O1
-O2
-O3
編譯器的優化選項的4個級別,-O0表示沒有優化,-O1爲缺省值,-O3優化級別最
高  

-g
只是編譯器,在編譯的時候,產生條是信息。

-gstabs
此選項以stabs格式聲稱調試信息,可是不包括gdb調試信息.

-gstabs+
此選項以stabs格式聲稱調試信息,而且包含僅供gdb使用的額外調試信息.

-ggdb
此選項將盡量的生成gdb的可使用的調試信息.
-static
此選項將禁止使用動態庫,因此,編譯出來的東西,通常都很大,也不須要什麼
動態鏈接庫,就能夠運行.
-share
此選項將盡可能使用動態庫,因此生成文件比較小,可是須要系統由動態庫.
-traditional
試圖讓編譯器支持傳統的C語言特性


GNU 的調試器稱爲 gdb,該程序是一個交互式工具,工做在字符模式。在 X Window 系統中,有一個 gdb 的
前端圖形工具,稱爲 xxgdb。gdb 是功能強大的調試程序,可完成以下的調試任務:
* 設置斷點;
* 監視程序變量的值;
* 程序的單步執行;
* 修改變量的值。
在可使用 gdb 調試程序以前,必須使用 -g 選項編譯源文件。可在 makefile 中以下定義 CFLAGS 變量:
CFLAGS = -g
運行 gdb 調試程序時一般使用以下的命令:
gdb progname

在 gdb 提示符處鍵入help,將列出命令的分類,主要的分類有:
* aliases:命令別名
* breakpoints:斷點定義;
* data:數據查看;
* files:指定並查看文件;
* internals:維護命令;
* running:程序執行;
* stack:調用棧查看;
* statu:狀態查看;
* tracepoints:跟蹤程序執行。
鍵入 help 後跟命令的分類名,可得到該類命令的詳細清單。


#DENO#
gdb 的經常使用命令
                表 1-4 經常使用的 gdb 命令
命令                        解釋
break NUM               在指定的行上設置斷點。
bt                      顯示全部的調用棧幀。該命令可用來顯示函數的調用順序。
clear                   刪除設置在特定源文件、特定行上的斷點。其用法爲:clear FILENAME:NUM。
continue                繼續執行正在調試的程序。該命令用在程序因爲處理信號或斷點而
                        致使中止運行時。
display EXPR            每次程序中止後顯示錶達式的值。表達式由程序定義的變量組成。
file FILE               裝載指定的可執行文件進行調試。
help NAME               顯示指定命令的幫助信息。
info break              顯示當前斷點清單,包括到達斷點處的次數等。
info files              顯示被調試文件的詳細信息。
info func               顯示全部的函數名稱。
info local              顯示當函數中的局部變量信息。
info prog               顯示被調試程序的執行狀態。
info var                顯示全部的全局和靜態變量名稱。
kill                    終止正被調試的程序。
list                    顯示源代碼段。
make                    在不退出 gdb 的狀況下運行 make 工具。
next                    在不單步執行進入其餘函數的狀況下,向前執行一行源代碼。
print EXPR              顯示錶達式 EXPR 的值。
quit                    退出當前程序
finsh                  直接執行完
setp                 這個和next 不一樣的地方是能夠進入函數內部
until                 直接運行到某行

另在編譯時 請使用gc -g -oo 不打開最優化,由於優化可能對調試不利,
1.8.5 gdb 使用範例
-----------------
清單 一個有錯誤的 C 源程序 bugging.c
-----------------
#include
#include

static char buff [256];
static char* string;
int main ()
{

    printf ("Please input a string: ");
    gets (string);

    printf ("\nYour string is: %s\n", string);
}
-----------------
上面這個程序很是簡單,其目的是接受用戶的輸入,而後將用戶的輸入打印出來。該程序使用了一個未通過初
始化的字符串地址 string,所以,編譯並運行以後,將出現 Segment Fault 錯誤:
$ gcc -o test -g test.c
$ ./test
Please input a string: asfd
Segmentation fault (core dumped)
爲了查找該程序中出現的問題,咱們利用 gdb,並按以下的步驟進行:
1.運行 gdb bugging 命令,裝入 bugging 可執行文件;
2.執行裝入的 bugging 命令;
3.使用 where 命令查看程序出錯的地方;
4.利用 list 命令查看調用 gets 函數附近的代碼;
5.惟一可以致使 gets 函數出錯的因素就是變量 string。用 print 命令查看 string 的值;
6.在 gdb 中,咱們能夠直接修改變量的值,只要將 string 取一個合法的指針值就能夠了,爲此,咱們在第
11 行處設置斷點;
7.程序從新運行到第 11 行處中止,這時,咱們能夠用 set variable 命令修改 string 的取值;
8.而後繼續運行,將看到正確的程序運行結果。

gcc和g++的區別是:
咱們在編譯c/c++代碼的時候,有人用gcc,有人用g++,因而各類說法都來了,譬如c代碼用gcc,而c++代碼用g++,或者說編譯用gcc,鏈 接用g++,一時也不知哪一個說法正確,若是再趕上個extern "C",分歧就更多了,這裏我想做個告終,畢竟知識的目的是使人更清醒,而不是更糊塗。

 
誤區一:gcc只能編譯c代碼,g++只能編譯c++代碼

二者均可以,可是請注意:
1.後綴爲.c的,gcc把它看成是C程序,而g++看成是c++程序;後綴爲.cpp的,二者都會認爲是c++程序,注意,雖然c++是c的超集,可是二者對語法的要求是有區別的,例如:
#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的語法規則,OK,沒問題,可是,一旦把後綴改成cpp,馬上報三個錯:「printString未定義」;
「cannot convert `char**' to `char*」;
」return-statement with no value「;
分別對應前面紅色標註的部分。可見C++的語法規則更加嚴謹一些。
2.編譯階段,g++會調用gcc,對於c++代碼,二者是等價的,可是由於gcc命令不能自動和C++程序使用的庫聯接,因此一般用g++來完成連接,爲了統一塊兒見,乾脆編譯/連接通通用g++了,這就給人一種錯覺,好像cpp程序只能用g++似的。

 
誤區二:gcc不會定義__cplusplus宏,而g++會

實際上,這個宏只是標誌着編譯器將會把代碼按C仍是C++語法來解釋,如上所述,若是後綴爲.c,而且採用gcc編譯器,則該宏就是未定義的,不然,就是已定義。

 
誤區三:編譯只能用gcc,連接只能用g++

嚴格來講,這句話不算錯誤,可是它混淆了概念,
應該這樣說:編譯能夠用gcc/g++,而連接能夠用g++或者gcc -lstdc++ 。由於gcc命令不能自動和C++程序使用的庫聯接,因此一般使用g++來完成聯接。但在編譯階段,g++會自動調用gcc,兩者等價。

 
誤區四:extern "C"與gcc/g++有關係


實際上並沒有關係,不管是gcc仍是g++,用extern "c"時,都是以C的命名方式來爲symbol命名,不然,都以c++方式命名。



++++++++++++++++++++++++++++
我本身的總結:
1> 在連接階段,gcc -lstdc++等價於g++,若是程序使用了C++的庫,不加-lstdc++就會出現不少報告說undefined的連接錯誤。
2>一條避免犯錯的辦法就是:編譯連接c程序用gcc;編譯連接c++程序用g++

相關文章
相關標籤/搜索