預備知識
安裝vim:
(針對Ubuntu,使用 apt 源安裝 vim)apt-get install vim
(針對 centos、redhat,使用 yum 源安裝 vim)yum install vim
配置vim:
安裝vim並配置 ~/.vimrc 文件使得vim能夠支持語法高亮、自動縮進等等功能。目前使用的 vimrc 配置文件的內容如下,進行基本的 c/c++ 編程已經足夠了(適用於類 UNIX 系統):

" 顯示行號 set number " 顯示標尺 set ruler " 歷史紀錄 set history=1000 " 輸入的命令顯示出來,看的清楚些 set showcmd " 狀態行顯示的內容 set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ %{strftime(\"%d/%m/%y\ -\ %H:%M\")} " 啟動顯示狀態行1,總是顯示狀態行2 set laststatus=2 " 語法高亮顯示 syntax on set fileencodings=utf-8,gb2312,gbk,cp936,latin-1 set fileencoding=utf-8 set termencoding=utf-8 set fileformat=unix set encoding=utf-8 " 配色方案 colorscheme desert " 指定配色方案是256色 set t_Co=256 set wildmenu " 去掉有關vi一致性模式,避免以前版本的一些bug和局限,解決backspace不能使用的問題 set nocompatible set backspace=indent,eol,start set backspace=2 " 啟用自動對齊功能,把上一行的對齊格式應用到下一行 set autoindent " 依據上面的格式,智能的選擇對齊方式,對於類似C語言編寫很有用處 set smartindent " vim禁用自動備份 set nobackup set nowritebackup set noswapfile " 用空格代替tab set expandtab " 設置顯示制表符的空格字符個數,改進tab縮進值,默認為8,現改為4 set tabstop=4 " 統一縮進為4,方便在開啟了et后使用退格(backspace)鍵,每次退格將刪除X個空格 set softtabstop=4 " 設定自動縮進為4個字符,程序中自動縮進所使用的空白長度 set shiftwidth=4 " 設置幫助文件為中文(需要安裝vimcdoc文檔) set helplang=cn " 顯示匹配的括號 set showmatch " 文件縮進及tab個數 au FileType html,python,vim,javascript setl shiftwidth=4 au FileType html,python,vim,javascript setl tabstop=4 au FileType java,php setl shiftwidth=4 au FileType java,php setl tabstop=4 " 高亮搜索的字符串 set hlsearch " 檢測文件的類型 filetype on filetype plugin on filetype indent on " C風格縮進 set cindent set completeopt=longest,menu " 功能設置 " 去掉輸入錯誤提示聲音 set noeb " 自動保存 set autowrite " 突出顯示當前行 set cursorline " 突出顯示當前列 set cursorcolumn "設置光標樣式為豎線vertical bar " Change cursor shape between insert and normal mode in iTerm2.app "if $TERM_PROGRAM =~ "iTerm" let &t_SI = "\<Esc>]50;CursorShape=1\x7" " Vertical bar in insert mode let &t_EI = "\<Esc>]50;CursorShape=0\x7" " Block in normal mode "endif " 共享剪貼板 set clipboard+=unnamed " 文件被改動時自動載入 set autoread " 頂部底部保持3行距離 set scrolloff=3
如果還想更舒服地編程,可以使用vim插件實現高級自動補全,快速定位、美化vim等等...那么最好先學習github的使用(如搜索廖雪峰的github教程),並在github上搜索 k-vim 並一鍵安裝。
完整的編譯並執行cpp文件過程
(一)代碼編寫
1. 啟動終端;
2. 輸入vim test.cpp,新建了一個文件叫做“test.cpp”;如果以前已經建立過這個文件,則是打開這個名字的文件。
3. 默認進入的是命令模式,輸入 i、a、o等進入編輯插入模式,分別對應於當前位置之前、之后插入和插入一行。
如果要刪除當前正在編輯的那一行的內容(刪除一個字符,刪除一個字,刪除一行),則必須按下esc鍵回到命令模式,分別使用x(刪除一個字符)、dw(刪除一個字)、dd(刪除一行)來進行刪除。
如果要撤銷某此操作,回到命令模式,然后輸入命令u(undo)來撤銷操作;如果要恢復撤銷的內容,則在命令模式下,輸入命令":redo"或者是":Control鍵+r",在沒有設置compatible的情況下,可以作多次的撤銷和恢復;
4. 編輯結束,輸入":w"表明存盤,然后輸入“:q!”退出vim編輯器;也可以直接輸入“:wq!”直接完成這兩個步驟。
(二)代碼編譯運行
設“test.cpp”文件的內容是:
#include <iostream> int main(void) { std::cout << "hello, world" << endl; return 0; }
1. 對於這個.cpp文件,使用以下的命令進行文件的編譯:
gcc -Wall test.cpp -o test -lstdc++ //必須加上 -lstdc++ 選項用來通知鏈接器鏈接靜態庫 libstdc++.a, //否則會因為找不到庫函數而出錯
或者直接使用編譯c++(.cpp)文件專用的命令g++,如下:
g++ -Wall test.cpp -o test
該命令將文件‘test.cpp’中的代碼編譯為機器碼並存儲在可執行文件 ‘test’中。機器碼的文件名是通過 -o 選項指定的,該選項通常作為命令行中的最后一個參數。如果被省略,輸出文件默認為 ‘a.out’。
如果當前目錄中與可執行文件重名的文件已經存在,則它將被復蓋。
選項 -Wall 開啟編譯器幾乎所有常用的警告──強烈建議你始終使用該選項。編譯器有很多其他的警告選項,但 -Wall 是最常用的。當編寫 C 或 C++ 程序時編譯器警告非常有助於檢測程序存在的問題。在最新幾個版本的 g++ 里 -Wall 已是默認的選項,在編譯時可無需再加入該選項,所以你也可以這么用:
g++ test.cpp
本例中,編譯器使用了 -Wall 選項而沒產生任何警告,因為示例程序是完全合法的。
另外:如果一開始建立了一個“test.c”的C語言類型的文件,內容如下;
#include <stdio.h> int main(void) { printf("Hello, world!/n"); return 0; }
編譯時使用“gcc -Wall test.c -o testc”命令。另外必須注意的是,在c文件中不能出現c++的庫,比如#include <iostream.h>就會報錯,但是cpp文件包含c語言的庫卻是可以的。
2. 運行:
./test
這個命令將可執行文件載入內存,並使 CPU 開始執行其包含的指令。 路徑“./”指代當前目錄,因此“./test” 載入並執行當前目錄下的可執行文件 ‘test’。
運行結果為:
hello, world
(三)編譯多個源文件 (可跳過)
1. 多源文件示例
將上面的"test.cpp"分解為三個不同的文件‘main.cpp’、‘test_fn.cpp’和頭文件‘test.h’。
(1)主程序‘main.cpp’如下:
#include "test.h" int main() { test("hello world!"); return 0; }
(2)函數聲明文件"test.h"如下內容:
void test(const char* name);
(3)函數實現文件"test_fn.cpp"的內容如下:
#include <iostream> using namespace std; #include "test.h" void test(const char* name) { cout<<"Hello World!"<<endl; }
2. 多文件編譯
g++ -Wall main.cpp test_fn.cpp -o newTest
本例中,我們使用選項 -o 為可執行文件指定了一個不同的名字 newTest。注意到頭文件‘test.h’並未在命令行中指定,這是因為它已經在main.cpp中包含。
(四)簡單的makeFile文件 (可跳過)
make命令 從 makefile(默認是當前目錄下的名為‘makefile’的文件)中讀取項目的描述。makefile指定了一系列目標(比如可執行文件)和依賴(比如對象文件和源文件)的編譯規則,其格式如下:
目標: 依賴
命令
對每一個目標,make 檢查其對應的依賴文件修改時間來確定該目標是否需要利用對應的命令重新建立。注意到,makefile 中命令行必須以單個的 TAB 字符進行縮進,不能是空格(糾正:就是空格而不是TAB)。
GNU Make 包含許多默認的規則(參見隱含規則)來簡化 makefile 的構建。比如說,它們指定‘.o’文件可以通過編譯‘.c’文件得到,可執行文件可以通過將‘.o’鏈接到一起獲得。隱含規則通過被叫做make變量的東西所指定,比如 CC(C 語言編譯器)和 CFLAGS(C程序的編譯選項);在makefile文件中它們通過獨占一行的 變量=值 的形式被設置。對 C++ ,其等價的變量是CXX和CXXFLAGS,而變量CPPFLAGS則是編譯預處理選項。
1. 現在為上面的“編譯多個源文件”示例創建一個簡單的makefile文件,內容如下:
CXXC=g++ CXXFLAGS=-Wall newTest: main.o test_fn.o //使用了隱含規則 cpp-->o clean: rm -f newTest main.o test_fn.o
該makefile文件可以這樣來讀:使用 C++語言編譯器 g++,和編譯選項‘-Wall’,從對象文件‘test.o’和‘test_fn.o’生成目標可執行文件 newTest(文件‘test.o’和‘test_fn.o’通過隱含規則分別由‘test.c’和‘test_fn.c’生成)。目標clean沒有依賴文件,它只是簡單地移除所有編譯生成的文件。rm命令的選項 ‘-f’(force) 抑制文件不存在時產生的錯誤消息。
2. 要使用該 makefile 文件,輸入 make命令。不加參數調用make時,makefile文件中的第一個目標被建立,從而生成可執行文件‘newTest’,終端會有如下輸出:
$ make g++ -Wall -c -o main.o main.cpp g++ -Wall -c -o test_fn.o test_fn.cpp g++ main.o test_fn.o -o newTest 運行該可執行文件: $ ./newTest Hello, world!
3. 一個源文件被修改要重新生成可執行文件,簡單地再次輸入 make 即可。通過檢查目標文件和依賴文件的時間戳,程序 make 可識別哪些文件已經修改並依據對應的規則更新其對應的目標文件:
$ vim test.cpp $ make //重新make g++ -Wall -c -o test.o test.c //此時只make該被修改的文件test.cpp g++ test.o test_fn.o -o newTest
運行結果:
$ ./newTest
Hello, world!
4. 最后,移除 make 生成的文件,輸入“make clean”,顯示如下:
$ make clean
rm -f hello hello.o hello_fn.o
總結: makefile文件類似一個編譯連接程序的批處理文件,所有的命令要作的事情寫進一個叫做makefile的文件中,然后使用make命令可以執行這個類似批處理文件的文件makefile。一個專業的 makefile文件通常包含用於安裝(make install)和
測試(make check)等額外的目標。
本例子中涉及到的例子都足夠簡單以至於可以完全不需要makefile,但是對任何大些的程序都使用 makefile文件是很有必要的。
(五)鏈接外部庫
庫是預編譯的目標文件(object files)的集合,它們可被鏈接進程序。靜態庫以后綴為‘.a’的特殊的存檔文件(archive file)存儲。
標准系統庫可在目錄 /usr/lib 與 /lib 中找到。比如,在類 Unix 系統中 C 語言的數學庫一般存儲為文件 /usr/lib/libm.a。該庫中函數的原型聲明在頭文件 /usr/include/math.h 中。C 標准庫本身存儲為 /usr/lib/libc.a,它包含 ANSI/ISO C 標准指定的函數,比如‘printf’。對每一個 C 程序來說,libc.a 都默認被鏈接。
下面的是一個調用數學庫 libm.a 中 sin 函數的的例子,創建文件calc.c:
#include <math.h> #include <stdio.h> int main (void) { double x = sin (2.0); printf ("The value of sin(2.0) is %f/n", x); return 0; }
嘗試單獨從該文件生成一個可執行文件將導致一個鏈接階段的錯誤:
$ gcc -Wall calc.c -o calc /tmp/ccbR6Ojm.o: In function 'main': /tmp/ccbR6Ojm.o(.text+0x19): undefined reference to ‘sin’
函數 sin,未在本程序中定義也不在默認庫‘libc.a’中;除非被指定,編譯器也不會鏈接‘libm.a’。
1. 法一
為使編譯器能將 sin 鏈接進主程序‘calc.c’,我們需要提供數學庫‘libm.a’。一個容易想到但比較麻煩的做法是在命令行中顯式地指定它:
$ gcc -Wall calc.c /usr/lib/libm.a -o calc
函數庫‘libm.a’包含所有數學函數的目標文件,比如sin,cos,exp,log及sqrt。鏈接器將搜索所有文件來找到包含 sin 的目標文件。一旦包含 sin 的目標文件被找到,主程序就能被鏈接,一個完整的可執行文件就可生成了:
$ ./calc The value of sin(2.0) is 0.909297
可執行文件包含主程序的機器碼以及函數庫‘libm.a’中 sin 對應的機器碼。
2. 法二
為避免在命令行中指定長長的路徑,編譯器為鏈接函數庫提供了快捷的選項‘-l’。例如,下面的命令
$ gcc -Wall calc.c -lm -o calc
與我們上面指定庫全路徑‘/usr/lib/libm.a’的命令等價。
一般來說,選項 -lNAME使鏈接器嘗試鏈接系統庫目錄中的函數庫文件 libNAME.a。一個大型的程序通常要使用很多 -l 選項來指定要鏈接的數學庫,圖形庫,網絡庫等。
如果想要使用c++11標准需要顯示鏈接 -std=c++11,並保持 g++ 版本在4.8以上,如下
g++ test.cpp -std=c++11