首先,聲明一下這是一個(gè)系列的文章。至于整個(gè)系列有多少篇,筆者也不知道,不知道有多少篇,也不知道多久會(huì)更新一篇。反正只有一個(gè)原則,寫(xiě)出來(lái)的文 章能見(jiàn)得人才會(huì)公布出來(lái)。另外,我不是叫你逃課,而是覺(jué)得聽(tīng)課只是一般學(xué)生做的,聽(tīng)課的時(shí)候把該聽(tīng)的聽(tīng)了,不該聽(tīng)的聽(tīng)過(guò)就算了,課堂上的東西只不過(guò)是大千 編程界里細(xì)沙一粒也稱(chēng)不上,真正牛的人從不滿(mǎn)足那一小點(diǎn)知識(shí),有些事太認(rèn)真你就輸了,世界很大,不要局限自己的視野,那樣會(huì)很累。
首先:整個(gè)系統(tǒng)環(huán)境都是基于linux平臺(tái)上的,如果有興趣你可以參考這里去學(xué)習(xí)linux:如何成為一個(gè)真正在路上的Linuxer ,也推廣下團(tuán)隊(duì)剛搭建出的LinuxCoder 社區(qū)。
編譯器用的gcc、g++,沒(méi)有請(qǐng)先自行安裝。
編譯第一個(gè)可執(zhí)行文件
第一篇文章,照例寫(xiě)個(gè)最經(jīng)典的hellow word 程序吧。(代碼1)
// code by lfly
// 2014-11-22
#include <iostream>
using namespace std ;
int main( int argc, char **argv)
{
cout << “Hellow World!” << endl ;
return 0 ;
}
很簡(jiǎn)單的一段代碼,最后返回0表示成功退出,返回其它值代表的是某種錯(cuò)誤(看具體值)。保存為hellow.cpp文件然后編譯運(yùn)行下:
lfly@programfish:~/project/c> ls hellow.cpp
lfly@programfish:~/project/c> g++ hellow.cpp -o hellow.o
lfly@programfish:~/project/c> ls hellow.cpp hellow.o
lfly@programfish:~/project/c>
-o是指定結(jié)果文件名,這里編譯成目標(biāo)文件hellow.o
如果不用-o指定文件名,默認(rèn)是編譯成a.out文件的。
.out文件是編譯鏈接成的可執(zhí)行文件,而.o文件一般是編譯出來(lái)的一個(gè)目標(biāo)文件,還沒(méi)有鏈接的。
但是Linux下是不以后綴名來(lái)區(qū)別是否是可執(zhí)行文件,區(qū)別的標(biāo)準(zhǔn)只有一個(gè):該文件在對(duì)應(yīng)的用戶(hù)下有沒(méi)有執(zhí)行權(quán)限(x權(quán)限)。 好了,運(yùn)行一下:
lfly@programfish:~/project/c> ./hellow.o
Hellow World!
正是我想要的結(jié)果: Hellow World!
main 函數(shù)參數(shù):
main 函數(shù)里有兩個(gè)參數(shù),第一個(gè)是int類(lèi)型argc,表示傳入main函數(shù)的參數(shù)個(gè)數(shù)。第二個(gè)是一個(gè)二維字符指針argv,保存了各個(gè)傳入的參數(shù)。這里注 意,argv[0]是保存了執(zhí)行這個(gè)可執(zhí)行文件時(shí)的路徑,后面argv[1]到argv[argc-1]才是保存了用戶(hù)傳入的參數(shù)(如果有的話(huà))。 這里改動(dòng)一下程序:(代碼2)
// code by lfly
// 2014-11-22
#include <iostream>
using namespace std ;
int main( int argc, char **argv)
{
cout << “argc is: ” << argc << endl ;
for ( int i=0; i<argc; ++i )
{
cout << argv[i] << endl ;
}
return 0 ;
}
改成這個(gè)樣子,輸出數(shù)量argc和argv里的各個(gè)字符串。依然是上面的編譯命令然后:
g++ hellow.cpp -o hellow.o
然后隨便加兩個(gè)參數(shù)hellow、world運(yùn)行一下:
lfly@programfish:~/project/c> ./hellow.o hellow world
argc is: 3 .
/hellow.o
hellow
world
可以看到參數(shù)數(shù)量為3,因?yàn)槟J(rèn)的第一個(gè)參數(shù)是執(zhí)行的路徑(這里為./hellow.o)其余兩個(gè)為傳入的hellow 及world
注意:main函數(shù)可以寫(xiě)成不帶參數(shù)或(void)的。而main函數(shù)最初最初是不帶參數(shù)的。想了解main函數(shù)身世請(qǐng)看這里:你所未必了解的main()函數(shù)的事情 http://www.nowamagic.net/librarys/veda/detail/96
窺探編譯與鏈接過(guò)程
g++編譯鏈接文件過(guò)程:
預(yù)處理 —> 編譯(匯編文件) —> 匯編(機(jī)器碼) —> 鏈接(可執(zhí)行程序)
1預(yù)處理過(guò)程
生成.i文件,這一下由預(yù)處理器cpp程序執(zhí)行。
cpp是一個(gè)可執(zhí)行程序,一般路徑為/usr/bin/cpp(可能是一個(gè)鏈接),你可以用find命令去搜索一下具體路徑。預(yù)處理器會(huì)讀入源代碼然后查找出預(yù)處理指令(宏定義、文件包含、條件編譯),這些指令以#開(kāi)頭。
-
宏定義
宏定義是指#define指令,預(yù)處理過(guò)程會(huì)把這些宏展開(kāi),例如 #define DF 10
預(yù)處理會(huì)把程序代碼里出現(xiàn)的DF獨(dú)立組合替換成10,這是簡(jiǎn)單的宏定義,至于帶參數(shù)的宏定義在這里不作討論。
-
文件包含
指#include 指令,預(yù)處理器會(huì)把包含到的頭文件的內(nèi)容替換到這個(gè)#include 指令。
-
條件編譯
#ifdef(#ifndef)與#endif指令,這些指令很大作用是使編譯出來(lái)的目 標(biāo)文件不會(huì)過(guò)大,你想想上面的#include指令會(huì)把一個(gè)頭文件的內(nèi)容替換到cpp文件里,假如你大意重復(fù)包含了文件(文件A包含文件B,在文件C里包 含了A,然后也用到B所以包含了B,那么C就包含了兩次B),這種情況在復(fù)雜的工程很難避免。所以用條件編譯可以?xún)?yōu)化你的程序,當(dāng)然它還有其它別的重要的 作用,這里不討論。
除了處理預(yù)編譯指令,預(yù)處理器還會(huì)刪掉你的注釋?zhuān)C(jī)器不看你的注釋?zhuān)烙?jì)也看不懂)。然后還有保留#pragma指令。
好了,現(xiàn)在來(lái)看看我們的hellow world預(yù)處理后會(huì)是什么樣子的。簡(jiǎn)單起見(jiàn),使用上面代碼1作為源代碼,使用g++ -E 預(yù)編譯(當(dāng)然你可以直接使用cpp命令)
g++ -E hellow.cpp -o hellow.i
然后來(lái)看一下預(yù)編譯得到hellow.i這個(gè)文件的內(nèi)容:
簡(jiǎn)單幾行代碼預(yù)編譯后得到的文件足足有17563行。而我開(kāi)頭的兩行注釋確實(shí)沒(méi)有了。
2編譯成匯編文件
這個(gè)過(guò)程是把預(yù)編譯后的代碼編譯成匯編代碼,由編譯器egcs執(zhí)行。下面來(lái)編譯一下我們得到的hellow.i文件:
g++ -S hellow.i -o hellow.s
然后查看一下hellow.s文件:
都是匯編代碼,學(xué)匯編的記得保重身體啊…..
3匯編過(guò)程
這一步就可以得到.o目標(biāo)文件了。過(guò)程由匯編器as執(zhí)行,把上面得到的hellow.s文件里的匯編指令逐條翻譯成機(jī)器碼。
g++ -C hellow.s -o hellow.o
4鏈接過(guò)程
由鏈接器ld完成,把多個(gè).o的機(jī)器碼鏈接成.out這樣的可執(zhí)行文件(當(dāng)然后綴名不是重點(diǎn))。注意,我這里的只有一個(gè).cpp文件,所以就只有一個(gè).o文件,不需要鏈接,這只是示例,但是正常工程下肯定不止這一個(gè)文件,那時(shí)候就要鏈接成可執(zhí)行文件才可以運(yùn)行了。
以上是Linux平臺(tái)里的示例,你可以在windows下使用g++做上面同樣的步驟。但作為程序猿,建議你使用linux做開(kāi)發(fā),不要問(wèn)為什么,可以找我博客里關(guān)于linux的文章看看。 第一篇就討論到這里吧,下次更新再討論其它問(wèn)題。
訪(fǎng)問(wèn) LinuxCoder程序員社區(qū) http://linuxcoder.org
轉(zhuǎn)載原創(chuàng)文章請(qǐng)注明:“作者:廣州Linux愛(ài)好者+云計(jì)算 刁金明” ,謝謝合作
學(xué)者網(wǎng)



評(píng)論 0