gcc g++ 支援c++11編譯的標準和區別
g++ -g -Wall -std=c++11 main.cpp
gcc -g -Wall -std=c11 main.cpp
如果不想每次寫這個-std=C++11這個選項該怎麼辦呢?
方法1:寫Makefile
方法2:取別名 :alias g++11="g++ -std=c++11"
--------------------------------------------------------------------------------------------------------------------------------
一般而言,在Linux下編譯程式分為以下4個階段:
- 預處理:編譯處理巨集定義等巨集命令(eg:#define)——生成字尾為“.i”的檔案
- 編譯:將預處理後的檔案轉換成組合語言——生成字尾為“.s”的檔案
- 彙編:由彙編生成的檔案翻譯為二進位制目標檔案——生成字尾為“.o”的檔案
- 連線:多個目標檔案(二進位制)結合庫函式等綜合成的能直接獨立執行的執行檔案——生成字尾為“.out”的檔案
在Linux下執行gcc與g++編譯C++檔案的差別:
- 字尾為.c的,gcc把它當作是C程式(cc/cpp才判定為C++源程式),而g++當作是c++程式
- gcc無法進行庫檔案的連線,即無法編譯完成步驟4;而g++則能完整編譯出可執行檔案。(實質上,g++從步驟1-步驟3均是呼叫gcc完成,步驟4連線則由自己完成)
gcc -E 執行到步驟1,只處理巨集命令,需要用重定向生成檔案
gcc -S 執行到步驟2,生成檔案.s
gcc -c 執行到步驟3,生成檔案.o
g++ 分別編譯於連線 .cc檔案與.o檔案
誤區一: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++方式命名。試驗如下:
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++命名有什麼不同
[
[[email protected] G++]# less me.s
.globl _Z9CppPrintfv //注意此函式的命名
.type CppPrintf, @function
[[email protected] GCC]# gcc -S me.cpp
[[email protected] GCC]# less me.s
.globl _Z9CppPrintfv //注意此函式的命名
.type CppPrintf, @function
完全相同!
2. 去掉me.h中extern "C",看用gcc和g++命名有什麼不同
[[email protected] GCC]# gcc -S me.cpp
[[email protected] GCC]# less me.s
.globl _Z9CppPrintfv //注意此函式的命名
.type _Z9CppPrintfv, @function
[[email protected] G++]# g++ -S me.cpp
[[email protected] 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
相關推薦
gcc g++ 支援c++11編譯的標準和區別
g++ -g -Wall -std=c++11 main.cpp gcc -g -Wall -std=c11 main.cpp 如果不想每次寫這個-std=C++11這個選項該怎麼辦呢? 方法1:寫Makefile 方法2:取別名 :alias g++11
gcc/g++以c++11編譯
pragma exp .cpp erro expect span 類定義 cte before 方法一: //在程序頭加上預定義編譯器命令 #pragma GCC diagnostic error "-std=c++11" //通過#pragma 指示 GCC編譯器處理錯誤
C++中數字與字串之間的轉換(包括C++11新標準和寬窄字元轉換)
1、字串數字之間的轉換 (1)string --> char * string str("OK"); char * p = str.c_str(); (2)char * -->string char *p = "OK"; string str(p); (3)char *
linux下安裝或升級GCC 4.8,以支援C++11標準
C++11標準在2011年8月份獲得一致通過,這是自1998年後C++語言第一次大修訂,對C++語言進行了改進和擴充。隨後各編譯器廠商都各自實現或部分實現了C++中的特性 。 如需檢視各編譯器對C++11的支援程度,請參看文章: 轉自:http://www.d
#gcc4.7.2編譯以支援c++11標準,解決not a member問題
使用g++4.7.2熟悉c++11,遇到下面問題。。 'thread' isnotamemberof 'std 'yield' is not a member of 'std::this_thread' sleep_for’ is not a member of ‘st
RedHat gcc編譯器版本升級到4.8.2支援C++11標準
原來環境資訊 Red Hat Enterprise Linux Server release 6.4 (Santiago) gcc4.4.7 升級到gcc4.8.2 gcc4.8以上版本才支援C++11標準,網上很多都是裝的4.8系列的版本,
linux之讓終端支援C++11/14編譯cpp檔案
1 問題 我們的專案很多智慧指標,但是我linux的終端肯定不支援C++11/14, 我們平時都是用的下面的命令編譯c++檔案 g++ -g file.cpp -o file r 如果是用c++11編譯需要改成如下 g++ -g -Wall -std=c+
linux下安裝或升級GCC4.8.2,以支援C++11標準[轉]
在編譯kenlm的時候需要安裝gcc, 然後還需要安裝g++。 g++安裝命令:sudo apt-get install g++ ----------------------以下為網上轉載內容,加上自己修改------------------ 本文主要介紹在Linux系統下,如何升級GCC以支援C+
CentOS上升級gcc編譯器使支援C++11
首先向博主致敬,好的東西拿來共享了,用一下不錯。 https://blog.csdn.net/clirus/article/details/62424517 0. 目標 最近在學習c++11,我本機裝的CentOS編譯器較老,不支援C++11的新特性,所以我需要把g
Ubuntu升級g++-4.8以支援C++11
也許你和我一樣在升級g++到4.8後發現用g++ a.cpp -o a還是提示編譯錯誤,那這篇文章給你答案。 轉自:http://my.oschina.net/zenglingfan/blog/169564 1. 安裝 gcc-4.8 為了使用C++ 11, 須安裝 gcc
GCC 升級4.8 支援c++11
gcc 升級到4.8 用來支援c++11 1)cd gcc-4.8.1 , ./contrib/download_prerequisites 下載依賴 2) cd .. , mkdir gcc-build-4.8.1 , cd gcc-build-4.8.1,
NDK編譯支援C++11
APP_CPPFLAGS += -std=c++11 // APP_CPPFLAGS += -std=gnu++11 NDK_TOOLCHAIN_VERSION=4.8 APP_STL=gnustl_
linux下安裝或升級GCC 4.8以上版本(包括),以支援C++11
本文轉載自:http://www.cnblogs.com/lizhenghn/p/3550996.html C++11標準在2011年8月份獲得一致通過,這是自1998年後C++語言第一次大修訂,對C++語言進行了改進和擴充。隨後各編譯器廠商都各自實現或部分實現了
linux下讓g++4.8.4支援C++11生效
最近在學習C++時遇到用g++編譯不支援auto型別的問題,如: 1.cpp:7:7: error: ‘a’ does not name a type auto a=r; ^ 後搜
配置Netbeans和codeblocks支援C++ 11
今天本來打算寫LeetCode中的。結果介面函式裡有一個unordered_set型別,編譯的時候找不著,查了一下才發現這是C++11裡的新標準類,我編譯器太老的,不支援。怎麼辦?升級編譯器唄。 NetBeans和Cygwin組合 因為習慣了NetBeans,所以編譯系
gcc -g -o -c分別是什麽意思
gcc linux-g為了調試用的 加個-g 是為了gdb 用,不然gdb用不到-o output_filename,確定輸出文件的名稱為output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項,gcc就給出預設的可執行文件a.out。-E:僅執行編譯預處理; -S:將C代碼轉換為匯編
C++11中lock_guard和unique_lock的區別
target san color member uri display each for clas c++11中有一個區域鎖lock_guard,還有第二個區域鎖unique_lock。 區域鎖lock_guard使用起來比較簡單,除了構造函數外沒有其他member fu
【C++11】unoedered_map和map(部分轉載)
好的 hash 比較 綜合 per 百萬 一點 應該 .net 1.結論 新版的hash_map都是unordered_map了,這裏只說unordered_map和map. 運行效率:unordered_map最高,而map效率較低但提供了穩定效率和有序的序列。 占用內存
C++11新標準
weak_ptr mat clas weak 自動完成 分配內存 初始化 val decltype 1. 新類型 long long和unsigned long long; char16_t 和 char32_t; 新增原始字符串; 2. 統一的初始化 C+
gcc/g++ 連結庫的編譯與連結
gcc/g++ 連結庫的編譯與連結 [email protected] http://blog.csdn.net/surgewong 程式編譯一般需要經預處理、編譯、彙編和連結幾個步驟。在實際應用中,有些公