gcc與g++的區別

一: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?
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++方式命名。試驗如下:
me.h:
extern "C" void CppPrintf(void);
?
me.cpp:
#include?
#include "me.h"
using namespace std;
void CppPrintf(void)
{
???? cout << "Hello\n";
}
?
test.cpp:
#include?
#include?
#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??????? //注意此函數的命名
??????? .type?? CppPrintf, @function
[root@root GCC]# gcc -S me.cpp
[root@root GCC]# less me.s
.globl _Z9CppPrintfv??????? //注意此函數的命名
??????? .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??????? //注意此函數的命名
??????? .type?? _Z9CppPrintfv, @function
[root@root G++]# g++ -S me.cpp
[root@root G++]# less me.s
.globl _Z9CppPrintfv??????? //注意此函數的命名
??????? .type?? _Z9CppPrintfv, @function
完全相同!
【結論】完全相同,可見extern "C"與采用gcc/g++并無關系,以上的試驗還間接的印證了前面的說法:在編譯階段,g++是調用gcc的。

二:gcc和g++的包含頭文件庫文件方法

-l參數就是用來指定程序要鏈接的庫,-l參數緊接著就是庫名,那么庫名跟真正的庫文件名有什么關系呢?就拿數學庫來說,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了。

好了現在我們知道怎么得到庫名,當我們自已要用到一個第三方提供的庫名字libtest.so,那么我們只要把 libtest.so拷貝到/usr/lib里,編譯時加上-ltest參數,我們就能用上libtest.so庫了(當然要用libtest.so庫里 的函數,我們還需要與libtest.so配套的頭文件)

放在/lib和/usr/lib和/usr/local/lib里的庫直接用-l參數就能鏈接了,但如果庫文件沒放 在這三個目錄里,而是放在其他目錄里,這時我們只用-l參數的話,鏈接還是會出錯,出錯信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是鏈接程序ld在那3個目錄里找不到libxxx.so,這時另外一個參數-L就派上用場了,比如常用的X11的庫,它在/usr /X11R6/lib目錄下,我們編譯時就要用-L/usr/X11R6/lib -lX11參數,-L參數跟著的是庫文件所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那鏈接參數就是-L /aaa/bbb/ccc -ltest

另外,大部分libxxxx.so只是一個鏈接,以RH9為例,比如libm.so它鏈接到/lib/libm.so.x,/lib/libm.so.6又鏈接到/lib/libm-2.3.2.so,

如果沒有這樣的鏈接,還是會出錯,因為ld只會找libxxxx.so,所以如果你要用到xxxx庫,而只有libxxxx.so.x或者libxxxx-x.x.x.so,做一個鏈接就可以了ln -s libxxxx-x.x.x.so libxxxx.so

手工來寫鏈接參數總是很麻煩的,還好很多庫開發包提供了生成鏈接參數的程序,名字一般叫xxxx-config,一般放在/usr/bin目錄下,比如

gtk1.2的鏈接參數生成程序是gtk-config,執行gtk-config --libs就能得到以下輸出"-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic

-lgmodule -lglib -ldl -lXi -lXext -lX11 -lm",這就是編譯一個gtk1.2程序所需的gtk鏈接參數,xxx-config除了--libs參數外還有一個參數是--cflags用來生成頭 文件包含目錄的,也就是-I參數,在下面我們將會講到。你可以試試執行gtk-config --libs --cflags,看看輸出結果

現在的問題就是怎樣用這些輸出結果了,最笨的方法就是復制粘貼或者照抄,聰明的辦法是在編譯命令行里加入這個 `xxxx-config --libs --cflags`,比如編譯一個gtk程序:gcc gtktest.c `gtk-config --libs --cflags`這樣就差不多了。注意`不是單引號,而是1鍵左邊那個鍵。

5、-include和-I參數

-include用來包含頭文件,但一般情況下包含頭文件都在源碼里用#include xxxxxx實現,-include參數很少用。-I參數是用來指定頭文件目錄,/usr/include目錄一般是不用指定的,gcc知道去那里找,但 是如果頭文件不在/usr/include里我們就要用-I參數指定了,比如頭文件放在/myinclude目錄里,那編譯命令行就要加上-I /myinclude參數了,如果不加你會得到一個"xxxx.h: No such file or directory"的錯誤。-I參數可以用相對路徑,比如頭文件在當前目錄,可以用-I.來指定。
?
結論例子:

g++ curltest.cpp -o curltest -L/mnt/hgfs/windows/curl-7.19.5/lib/.libs -lcurl -I/mnt/hgfs/windows/curl-7.19.5/include

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/383446.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383446.shtml
英文地址,請注明出處:http://en.pswp.cn/news/383446.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

交叉編譯openssl不修改Makefile的方法

網上流傳的方法都是要修改Makefile的cc值&#xff0c;我來說個不用修改的方法作者&#xff1a;帥得不敢出門 C哈哈堂<31843264>openssl 下載http://www.openssl.org/source/tar -xvf openssl-1.0.1c.tar.gzcd openssl-1.0.1c/CCarm-linux-gcc ./config no-asm shared -…

編譯boa過程記錄

boa是比較老的HTTP的本地Server&#xff0c;本文是針對0.94.13版本的編譯過程做出記錄 1.下載boa的程序包&#xff0c;本文的編譯是針對misp平臺的交叉編譯 2.在編譯之前&#xff0c;需要針對產品的文件系統和修改編譯時可能遇到的錯誤&#xff0c;修改相關的文件。 &#xff…

/dev/null 21 的作用

shell中可能經常能看到&#xff1a;>/dev/null 2>&1命令的結果可以通過%>的形式來定義輸出/dev/null 代表空設備文件> 代表重定向到哪里&#xff0c;例如&#xff1a;echo "123" > /home/123.txt1 表示stdout標準輸出&#xff0c;系統默認值是1&a…

移植wpa_supplicant 2.2問題

1.編譯libnl1.1問題 In file included from addr.c:28:0: ../include/netlink-local.h: In function __str2type: ../include/netlink-local.h:218:11: error: ULONG_MAX undeclared (first use in this function) ../include/netlink-local.h:218:11: note: each undeclared …

wpa_supplicant與wpa_cli之間通信過程

wpa_supplicant編譯&#xff1a; 1. wpa_supplicant/Android.mk : -- wpa_cli -- wpa_supplicant -- libwpa_client.so 2. hostapd/Android.mk : -- hostapd_cli -- hostapd 從通信層次上劃分&#xff0c;wpa_supplicant提供向上的控制接口 control interface&#xff0c;用于與…

Linux內核驅動之GPIO子系統(一)GPIO的使用

一 概述 Linux內核中gpio是最簡單&#xff0c;最常用的資源(和 interrupt ,dma,timer一樣)驅動程序&#xff0c;應用程序都能夠通過相應的接口使用gpio&#xff0c;gpio使用0&#xff5e;MAX_INT之間的整數標識&#xff0c;不能使用負數,gpio與硬件體系密切相關的,不過linux有一…

gpio_direction_output 與 gpio_set_value

gpio_set_value&#xff08;port_num,0/1&#xff09; 一般只是在這個GPIO口的寄存器上寫上某個值&#xff0c;至于這個端口是否設置為輸出&#xff0c;它就管不了&#xff01; 而gpio_direction_output &#xff08;port_num,0/1)&#xff0c;在某個GPIO口寫上某個值之后&…

內核ko模塊strip使用

編譯一個內核時&#xff0c;習慣性的在install目標下加了命令&#xff1a; $(STRIP) --strip-all --remove-section.note --remove-section.comment test.ko 結果在insmod test.ko時出現錯誤&#xff1a; test: module has no symbols (stripped?) .................. 上…

ubuntu下修復U盤只讀問題

1.通過mount指令查看u盤掛載的實際設備 /dev/sdb1 on /media/xuxuequan/0BEB-331A type vfat (rw,nosuid,nodev,uid1000,gid1000,shortnamemixed,dmask0077,utf81,showexec,flush,uhelperudisks2) 2.umount掛載點 umount /media/xuxuequan/0BEB-331A 3.fsck修復u盤設備 s…

mkfs.jffs2參數詳解

實例&#xff1a;mkfs.jffs2 -r rootfs -o rootfs.jffs2 -e 0x4000 --pad0x1000000 -s 0x200 -n mkfs.jffs2: Usage: mkfs.jffs2 [OPTIONS] Make a JFFS2 file system image from an existing directory tree Options: -p, --pad[SIZE] 用16進制來表示所要輸出檔案的大小&…

關于c語言字符串函數和一些內存函數的的簡介

關于c語言字符串函數和一些內存函數的的簡介 求字符串長度的函數 strlen函數介紹![在這里插入圖片描述](https://img-blog.csdnimg.cn/20190301142458376.jpg)注模擬實現 . [1 ]計數器方式 因為strlen 是求字符串長度的函數&#xff0c;所以不能改變字符串本身&#xff0c;所…

君正T20平臺生成jffs2格式rootfs

基于系統升級的考慮&#xff0c;這兩天在君正T20平臺上折騰如何生成jffs2 格式的rootfs。詳細的過程如下&#xff1a; 1.修改uboot中的分區參數&#xff1a; 修改為rootfs格式為jffs2的&#xff0c;且適當擴大rootfs分區大小。&#xff08;因jffs2的壓縮比不如只讀的squashfs…

用結構體寫一個簡單的通訊錄

一個簡單的通訊錄 通訊錄應該具備簡單的一些功能 1 增添聯系人 2 刪除聯系人 3 查找聯系人 4 修改聯系人 5 按名字給聯系人排序 6 查看通訊錄 除此之外&#xff0c;應該在實現上還應該具備一些其他的功能函數 比如 初始化通訊錄 這些都是功能函數&#xff0c;而整個函數入口應…

jffs2 啟動的常見的問題

Q&#xff1a;在啟動過程中出現at91sam user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000問題 A&#xff1a;在mkfs.jffs2的時候&#xff0c;加上-e 0x20000指定擦除塊的大小。-e是指定擦除塊的大小&#xff0c;我們使用的nandflash的塊大小為128K字節&#xf…

c動態內存管理

動態內存管理 我們之前要開辟內存用的方法都是定義變量&#xff0c;比如 但是上述開辟內存的方法有兩個特點 1空間開辟大小是固定的 2數組在申明的時候&#xff0c;必須指定數組的長度&#xff0c;它所需要的內存在編譯時分配 malloc和free c中提供一個動態內存開辟函數 這…

JFFS2文件系統掛載過程優化的分析報告

一 問題描述 在上電啟動優化中發現Linux系統下掛載JFFS2文件系統耗時較長&#xff0c;以128M的NOR FLASH為例&#xff0c;用時接近20秒。后續單板的FLASH容量為256M&#xff0c;時間會更長。如此長的掛載時間&#xff0c;會大增加系統的上電啟動時間。希望能對mount功能或JFFS…

右移函數(字符串,數組)

右移函數 以上是數組右移&#xff0c;將int換成char 把數組內容改成字符串就行。

關于jffs2文件系統如何掉電保護

JFFS2 是將節點信息保存在內存中 Flash上日志型文件系統的資料&#xff0c;了解到傳統的基于閃存轉換層&#xff08;FLT&#xff09;的文件系統存在的主要問題&#xff1a; 1. 效率低。因為每次都要把要修改的數據所在擦寫塊放入內存&#xff0c;產生了許多不必要的讀操作&…

c中指針簡介

c中指針簡介 首先我們來看一下指針的一些基本概念 ![在這里插入圖片描述](https://img 而對于指針的應用&#xff0c;平常有一些形式&#xff0c;總結了一下大概有這幾種用法 對于以上的幾種用法&#xff0c;我依次給出詳盡的解釋 //這是一個普通的整型變量 1 //首先從P 處開…

判斷一個字符串是否另一個字符串的右移后的

首先我們把需要判斷的字符串傳進來&#xff0c;開辟一塊大小為兩個字符串的長度總和加1的動態的空間&#xff0c;然后后字符串拷貝函數將一個字符串拷貝到開辟空降中&#xff0c;再將這個字符串再次連接到這塊動態的空間中&#xff0c;等于就是將一個字符串拷貝了兩遍。然后比較…