Linux 環境下使用g 編譯C

2021-08-16 06:21:26 字數 4458 閱讀 6267

下面是乙個儲存在檔案 helloworld.cpp 中乙個簡單的 c++ 程式的**:

/* helloworld.cpp */

#include

int main(

int argc,char

*argv)

程式使用定義在標頭檔案 iostream 中的 cout,向標準輸出寫入乙個簡單的字串。該**可用以下命令編譯為可執行檔案:

$ g++ helloworld.cpp
編譯器 g++ 通過檢查命令列中指定的檔案的字尾名可識別其為 c++ 源**檔案。編譯器預設的動作:編譯源**檔案生成物件檔案(object file),鏈結物件檔案和 libstdc++ 庫中的函式得到可執行程式。然後刪除物件檔案。由於命令列中未指定可執行程式的檔名,編譯器採用預設的 a.out。程式可以這樣來執行:

$ ./a.out

hello, world

更普遍的做法是通過 -o 選項指定可執行程式的檔名。下面的命令將產生名為 helloworld 的可執行檔案:

$ g++ helloworld.cpp -o helloworld
在命令列中輸入程式名可使之執行:

$ ./helloworld

hello, world

程式 g++ 是將 gcc 預設語言設為 c++ 的乙個特殊的版本,鏈結時它自動使用 c++ 標準庫而不用 c 標準庫。通過遵循原始碼的命名規範並指定對應庫的名字,用 gcc 來編譯鏈結 c++ 程式是可行的,如下例所示:

$ gcc helloworld.cpp -lstdc++ -o helloworld
選項 -l (ell) 通過新增字首 lib 和字尾 .a 將跟隨它的名字變換為庫的名字 libstdc++.a。而後它在標準庫路徑中查詢該庫。gcc 的編譯過程和輸出檔案與 g++ 是完全相同的。

在大多數系統中,gcc 安裝時會安裝一名為 c++ 的程式。如果被安裝,它和 g++ 是等同,如下例所示,用法也一致:

$ c++ helloworld.cpp -o helloworld

如果多於乙個的原始碼檔案在 g++ 命令中指定,它們都將被編譯並被鏈結成乙個單一的可執行檔案。下面是乙個名為 speak.h 的標頭檔案;它包含乙個僅含有乙個函式的類的定義:

/* speak.h */

#include

class speak

;

下面列出的是檔案 speak.cpp 的內容:包含 sayhello() 函式的函式體:

/* speak.cpp */

#include "speak.h"

void speak::

sayhello

(const

char

*str)

檔案 hellospeak.cpp 內是乙個使用 speak 類的程式:

/* hellospeak.cpp */

#include "speak.h"

int main(

int argc,char

*argv)

$ g++ hellospeak.cpp speak.cpp -o hellospeak
ps:這裡說一下為什麼在命令中沒有提到「speak.h「該檔案(原因是:在「speak.cpp「中包含有」#include"speak.h"「這句**,它的意思是搜尋系統頭檔案目錄之前將先在當前目錄中搜尋檔案「speak.h「。而」speak.h「正在該目錄中,不用再在命令中指定了)。

選項 -c 用來告訴編譯器編譯源**但不要執行鏈結,輸出結果為物件檔案。檔案預設名與原始碼檔名相同,只是將其字尾變為 .o。例如,下面的命令將編譯原始碼檔案 hellospeak.cpp 並生成物件檔案 hellospeak.o:

$ g++ -c hellospeak.cpp
命令 g++ 也能識別 .o 檔案並將其作為輸入檔案傳遞給鏈結器。下列命令將編譯原始碼檔案為物件檔案並將其鏈結成單一的可執行程式:

$ g++ -c hellospeak.cpp 

$ g++ -c speak.cpp

$ g++ hellospeak.o speak.o -o hellospeak

選項 -o 不僅僅能用來命名可執行檔案。它也用來命名編譯器輸出的其他檔案。例如:除了中間的物件檔案有不同的名字外,下列命令生將生成和上面完全相同的可執行檔案:

$ g++ -c hellospeak.cpp -o hspk1.o 

$ g++ -c speak.cpp -o hspk2.o

$ g++ hspk1.o hspk2.o -o hellospeak

選項 -e 使 g++ 將源**用編譯預處理器處理後不再執行其他動作。下面的命令預處理原始碼檔案 helloworld.cpp 並將結果顯示在標準輸出中:

$ g++ -e helloworld.cpp
本文前面所列出的 helloworld.cpp 的源**,僅僅有六行,而且該程式除了顯示一行文字外什麼都不做,但是,預處理後的版本將超過 1200 行。這主要是因為標頭檔案 iostream 被包含進來,而且它又包含了其他的標頭檔案,除此之外,還有若干個處理輸入和輸出的類的定義。

預處理過的檔案的 gcc 字尾為 .ii,它可以通過 -o 選項來生成,例如:

$ gcc -e helloworld.cpp -o helloworld.ii

選項 -s 指示編譯器將程式編譯成組合語言,輸出組合語言**而後結束。下面的命令將由 c++ 原始碼檔案生成組合語言檔案 helloworld.s:

$ g++ -s helloworld.cpp
生成的組合語言依賴於編譯器的目標平台。

靜態庫是編譯器生成的一系列物件檔案的集合。鏈結乙個程式時用庫中的物件檔案還是目錄中的物件檔案都是一樣的。庫中的成員包括普通函式,類定義,類的物件例項等等。靜態庫的另乙個名字叫歸檔檔案(archive),管理這種歸檔檔案的工具叫 ar 。

在下面的例子中,我們先建立兩個物件模組,然後用其生成靜態庫。

標頭檔案 say.h 包含函式 sayhello() 的原型和類 say 的定義:

/* say.h */

#include

void sayhello(

void

);class say

void saythis(

const

char

*str)

void saystring(

void

);};

下面是檔案 say.cpp 是我們要加入到靜態庫中的兩個物件檔案之一的原始碼。它包含 say 類中 saystring() 函式的定義體;類 say 的乙個例項 librarysay 的宣告也包含在內:

/* say.cpp */

#include "say.h"

void say::

saystring()

say librarysay(

"library instance of say"

);

原始碼檔案 sayhello.cpp 是我們要加入到靜態庫中的第二個物件檔案的原始碼。它包含函式 sayhello() 的定義:

/* sayhello.cpp */

#include "say.h"

void sayhello(

)

下面的命令序列將原始碼檔案編譯成物件檔案,命令 ar 將其存進庫中:

$ g++ -c sayhello.cpp

$ g++ -c say.cpp

$ ar -r libsay.a sayhello.o say.o

程式 ar 配合引數 -r 建立乙個新庫 libsay.a 並將命令列中列出的物件檔案插入。採用這種方法,如果庫不存在的話,引數 -r 將建立乙個新的庫,而如果庫存在的話,將用新的模組替換原來的模組。

下面是主程式 saymain.cpp,它呼叫庫 libsay.a 中的**:

/* saymain.cpp */

#include "say.h"

int main(

int argc,char

*argv)

$ g++ saymain.cpp libsay.a -o saymain
程式執行時,產生以下輸出:

hello from a static library

howdy from a static library

library instance of say

local instance of say

ps:如果乙個資料夾下有多個cpp檔案需要編譯的話,除了採用makefile的方式之外,還可以使用「g++ *.cpp -o hello",「hello為編譯生成的可執行檔案的名字」,編譯時要確保cpp檔案和他們各自所引用的標頭檔案在同乙個目錄下。

Linux環境使用g 編譯C

以下述c 的編譯為例 helloworld.cpp include intmain int argc,char ar 該 可用以下命令編譯 g helloworld.cpp 編譯器 g 通過檢查命令列中指定的檔案的字尾名,可識別其為 c 源 檔案。編譯器預設的動作 編譯源 檔案生成物件檔案 obje...

Ubuntu環境下使用g 編譯cpp檔案

第一次用g 編譯cpp檔案的時候報了undefined reference的錯誤,自定義類中的函式全部都無法找到,查詢資料後發現呼叫的類是需要鏈結的,本文以乙個小例子描述編譯的過程。其中class2類呼叫了class1類的成員函式,依賴於class1類,而test檔案呼叫了class2類的成員函式,...

linux環境下編譯C 檔案

最近需要將 上傳到github,順便使得 要在ubuntu上能夠編譯執行。稍微學習了一下ubuntu環境下的c 檔案編譯方式。隨便寫個簡單的程式 test.cpp include int main int argc,char argv 可以直接g test.cpp編譯,編譯器預設的動作 編譯源 檔案...