my blogs已遷移到 http://www.cnblogs.com/dzzy/
一.單個源.cpp檔案生成可執行程式
下面是一個儲存在檔案 helloworld.cpp 中一個簡單的 C++ 程式的程式碼:
/* helloworld.cpp */
#include <iostream>
int main()
{
std::cout << "hello, world" ;
return(0);
}
***** c++ helloworld.cpp -o hello -Wall
編譯器c++ 通過檢查命令列中指定的檔案的字尾名可識別其為 C++ 原始碼檔案,同時列印提示資訊。
編譯器預設的動作:編譯原始碼檔案生成物件檔案(object file)
連結物件檔案和 libstdc++ 庫中的函式得到可執行程式。然後刪除物件檔案。
由於命令列中未指定可執行程式的檔名,編譯器採用預設的 a.out。
程式可以這樣來執行:
***** ./hello
hello, world
程式c++/g++ 是將 gcc 預設語言設為 C++ 的一個特殊的版本,連結時它自動使用 C++ 標準庫而不用 C 標準庫。
通過遵循原始碼的命名規範並指定對應庫的名字,用 gcc 預設編譯c檔案,通過擴充套件來編譯連結 C++ 程式也是可行的,
如下例所示:
***** gcc helloworld.cpp -lstdc++ -o helloworld
選項 -l (ell) 通過新增字首 lib 和字尾 .a 將跟隨它的名字變換為庫的名字 libstdc++.a,而後它在標準庫路徑中查詢該庫。
gcc 的編譯過程和輸出檔案與 c++/g++ 是完全相同的。
二.預編譯處理和生成彙編程式碼
編譯預處理 選項 -E 使 c++ 將原始碼用編譯前處理器處理後不再執行其他動作。
下面的命令預處理原始碼檔案 helloworld.cpp 並將結果顯示在標準輸出中:
***** c++ -E helloworld.cpp
預處理後的版本將超過 12000 行。這主要是因為標頭檔案 iostream 被包含進來,
而且它又包含了其他的標頭檔案,除此之外,還有若干個處理輸入和輸出的類的定義。
預處理過的檔案的 GCC 字尾為 .ii,它可以通過 -o 選項來生成,
例如:
***** gcc -E helloworld.cpp -o helloworld.ii
生成彙編程式碼 選項 -S 指示編譯器將程式編譯成組合語言,輸出組合語言程式碼而後結束。
下面的命令將由 C++ 原始碼檔案生成組合語言檔案 helloworld.s:
***** c++ -S helloworld.cpp 生成的組合語言依賴於編譯器的目標
三.多個原始檔生成可執行程式de動態編譯
如果多於一個的原始碼檔案在c++ 命令中指定,它們都將被編譯並被連結成一個單一的可執行檔案。
下面是一個名為 speak.h 的標頭檔案;
它包含一個僅含有一個函式的類的定義:
/* stack.h */
#ifndef STACK_H_ #define STACK_H_
typedef unsigned long Item;
class Stack
{
private:
enum {MAX=10};
Item items[MAX];
int top;
public:
Stack();
bool isempty() const;
bool isfull() const;
bool push(const Item & item);
bool pop(Item & item); };
#endif
下面列出的是檔案 stack.cpp 的內容:
/* stack.cpp */
#include"stack.h"
Stack::Stack()
{
top=0;
}
bool Stack::isempty() const
{
return top==0;
}
bool Stack::isfull() const
{
return top==MAX;
}
bool Stack::push(const Item&item)
{
if(top<MAX)
{
items[top++]=item;
return true;
}
else return false;
}
bool Stack::pop(Item&item)
{
if(top>0)
{
item=items[--top];
return true;
}
else return false;
}
檔案 hellospeak.cpp 內是一個使用 stack 類的程式:
/* stacker.cpp*/
// stacker.cpp -- testing the Stack class
#include <iostream>
#include <cctype> // or ctype.h
#include "stack.h"
int main()
{
using namespace std;
Stack st; // create an empty stack
char ch;
unsigned long po;
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << '\a';
continue;
}
switch(ch)
{
case 'A':
case 'a': cout << "Enter a PO number to add: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p': if (st.isempty())
cout << "stack already empty\n";
else {
st.pop(po);
cout << "PO #" << po << " popped\n";
}
break;
}
cout << "Please enter A to add a purchase order,\n"
<< "P to process a PO, or Q to quit.\n";
}
cout << "Bye\n";
return 0;
}
下面這條命令將上述兩個原始碼檔案編譯連結成一個單一的可執行程式:
***** c++ stack.cpp stacker.cpp -o stacks
原始檔生成物件檔案
選項 -c 用來告訴編譯器編譯原始碼但不要執行連結,輸出結果為物件檔案,字尾變為 .o。
例如,下面的命令將編譯原始碼檔案 hellospeak.cpp 並生成物件檔案 hellospeak.o:
***** c++ -c stacker.cpp
命令 g++ 也能識別 .o 檔案並將其作為輸入檔案傳遞給連結器。
下列命令將編譯原始碼檔案為物件檔案並將其連結成單一的可執行程式:
***** c++ -c stacker.cpp
***** c++ -c stack.cpp
***** c++ stacker.o stack.o -o stacks
選項 -o 不僅僅能用來命名可執行檔案。它也用來命名編譯器輸出的其他檔案。
四.多個原始檔生成可執行程式de靜態編譯
建立靜態庫
靜態庫是編譯器生成的一系列物件檔案的集合。
連結一個程式時用庫中的物件檔案還是目錄中的物件檔案都是一樣的。
庫中的成員包括普通函式,類定義,類的物件例項等等。
靜態庫的另一個名字叫歸檔檔案(archive),管理這種歸檔檔案的工具叫 ar 。
在上面的例子中,我們先建立兩個物件模組,然後用其生成靜態庫。
原始碼檔案 stack.cpp 是我們要加入到靜態庫中的第一個物件檔案的原始碼。
原始碼檔案 stacker.cpp 是我們要加入到靜態庫中的第二個物件檔案的原始碼。
下面的命令序列將原始碼檔案編譯成物件檔案,命令 ar 將其存進庫中:
***** c++ -c stack.cpp
***** c++ -c stacker.cpp
***** ar -r lib.a stack.o stacker.o
程式 ar 配合引數 -r 建立一個新庫 lib.a 並將命令列中列出的物件檔案插入。
採用這種方法,如果庫不存在的話,引數 -r 將建立一個新的庫,
而如果庫存在的話,將用新的模組替換原來的模組。
如果有第三個.cpp檔案(main函式),或者沒有也可以直接編譯前面的.cpp
該程式可以下面的命令來編譯和連結:
***** c++ stacker.cpp lib.a -o main
剛剛學會的編譯方式還是蠻好用的。
PS: powershall也是蠻好用的畢竟不是黑漆漆的介面了233333.