在linux環境下編譯C 程式

2022-10-09 02:06:12 字數 4684 閱讀 1399

下面是乙個儲存在檔案helloworld.cpp中乙個簡單的 c++ 程式的**: 單個原始檔生成可執行程式

/* helloworld.cpp */

#include int main(int argc,char *ar**)

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

$  g++ helloworld.cpp
編譯器 g++ 通過檢查命令列中指定的檔案的字尾名可識別其為 c++ 源**檔案。

** 編譯器預設的動作:** 編譯源**檔案生成物件檔案(object file),鏈結物件檔案和 libstd c++ 庫中的函式得到可執行程式。然後刪除物件檔案。由於命令列中未指定可執行程式的檔名,編譯器採用預設的 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 *ar**)

$ 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++ -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");

原始碼檔案syshello.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 *ar**)

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

hello from a static library

howdy from a static library

library instance of saylocal instance of say

在linux環境下編譯C 程式

下面是乙個儲存在檔案helloworld.cpp中乙個簡單的 c 程式的 單個原始檔生成可執行程式 helloworld.cpp include int main int argc,char argv 程式使用定義在標頭檔案 iostream 中的 cout,向標準輸出寫入乙個簡單的字串。該 可用以...

在linux下編譯執行C 程式

頭一回。把windows下的程式挪到linux下,見這篇隨筆 1 編譯zthread,使用.configure失敗,直接編譯的,方法還是上面提到的那篇隨筆 2 編譯原始碼,最開始用的cc,後來老是報undefined reference,甚至hello world程式也報undefined refe...

linux環境下編譯C 檔案

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