程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 課堂裡學不到的C與C++那些事(一),課堂那些事

課堂裡學不到的C與C++那些事(一),課堂那些事

編輯:C++入門知識

課堂裡學不到的C與C++那些事(一),課堂那些事


首先,聲明一下這是一個系列的文章。至於整個系列有多少篇,筆者也不知道,不知道有多少篇,也不知道多久會更新一篇。反正只有一個原則,寫出來的文 章能見得人才會公布出來。另外,我不是叫你逃課,而是覺得聽課只是一般學生做的,聽課的時候把該聽的聽了,不該聽的聽過就算了,課堂上的東西只不過是大千 編程界裡細沙一粒也稱不上,真正牛的人從不滿足那一小點知識,有些事太認真你就輸了,世界很大,不要局限自己的視野,那樣會很累。

首先:整個系統環境都是基於linux平台上的,如果有興趣你可以參考這裡去學習linux:如何成為一個真正在路上的Linuxer   ,也推廣下團隊剛搭建出的LinuxCoder 社區。

編譯器用的gcc、g++,沒有請先自行安裝。

 

編譯第一個可執行文件

第一篇文章,照例寫個最經典的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 ;

}

很簡單的一段代碼,最後返回0表示成功退出,返回其它值代表的是某種錯誤(看具體值)。保存為hellow.cpp文件然後編譯運行下:

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是指定結果文件名,這裡編譯成目標文件hellow.o

如果不用-o指定文件名,默認是編譯成a.out文件的。

.out文件是編譯鏈接成的可執行文件,而.o文件一般是編譯出來的一個目標文件,還沒有鏈接的。

但是Linux下是不以後綴名來區別是否是可執行文件,區別的標准只有一個:該文件在對應的用戶下有沒有執行權限(x權限)。 好了,運行一下:

lfly@programfish:~/project/c> ./hellow.o

Hellow World!

正是我想要的結果: Hellow World!

 

main 函數參數:

main 函數裡有兩個參數,第一個是int類型argc,表示傳入main函數的參數個數。第二個是一個二維字符指針argv,保存了各個傳入的參數。這裡注 意,argv[0]是保存了執行這個可執行文件時的路徑,後面argv[1]到argv[argc-1]才是保存了用戶傳入的參數(如果有的話)。 這裡改動一下程序:(代碼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 ;

}

改成這個樣子,輸出數量argc和argv裡的各個字符串。依然是上面的編譯命令然後:

g++ hellow.cpp -o hellow.o

然後隨便加兩個參數hellow、world運行一下:

lfly@programfish:~/project/c> ./hellow.o  hellow  world

argc is: 3 .

/hellow.o

hellow

world

可以看到參數數量為3,因為默認的第一個參數是執行的路徑(這裡為./hellow.o)其余兩個為傳入的hellow 及world

注意:main函數可以寫成不帶參數或(void)的。而main函數最初最初是不帶參數的。想了解main函數身世請看這裡:你所未必了解的main()函數的事情 http://www.nowamagic.net/librarys/veda/detail/96

 

窺探編譯與鏈接過程

g++編譯鏈接文件過程:

預處理 —> 編譯(匯編文件) —> 匯編(機器碼) —> 鏈接(可執行程序)

1預處理過程

生成.i文件,這一下由預處理器cpp程序執行。

cpp是一個可執行程序,一般路徑為/usr/bin/cpp(可能是一個鏈接),你可以用find命令去搜索一下具體路徑。預處理器會讀入源代碼然後查找出預處理指令(宏定義、文件包含、條件編譯),這些指令以#開頭。

  •   宏定義

宏定義是指#define指令,預處理過程會把這些宏展開,例如        #define  DF  10

預處理會把程序代碼裡出現的DF獨立組合替換成10,這是簡單的宏定義,至於帶參數的宏定義在這裡不作討論。

  •   文件包含

指#include 指令,預處理器會把包含到的頭文件的內容替換到這個#include 指令。

  •   條件編譯

#ifdef(#ifndef)與#endif指令,這些指令很大作用是使編譯出來的目 標文件不會過大,你想想上面的#include指令會把一個頭文件的內容替換到cpp文件裡,假如你大意重復包含了文件(文件A包含文件B,在文件C裡包 含了A,然後也用到B所以包含了B,那麼C就包含了兩次B),這種情況在復雜的工程很難避免。所以用條件編譯可以優化你的程序,當然它還有其它別的重要的 作用,這裡不討論。

除了處理預編譯指令,預處理器還會刪掉你的注釋(機器不看你的注釋,估計也看不懂)。然後還有保留#pragma指令。

  好了,現在來看看我們的hellow world預處理後會是什麼樣子的。簡單起見,使用上面代碼1作為源代碼,使用g++ -E 預編譯(當然你可以直接使用cpp命令)

g++ -E hellow.cpp -o hellow.i

然後來看一下預編譯得到hellow.i這個文件的內容:

圖片1

簡單幾行代碼預編譯後得到的文件足足有17563行。而我開頭的兩行注釋確實沒有了。

2編譯成匯編文件    

這個過程是把預編譯後的代碼編譯成匯編代碼,由編譯器egcs執行。下面來編譯一下我們得到的hellow.i文件:

g++ -S hellow.i -o hellow.s

然後查看一下hellow.s文件:

圖片2

都是匯編代碼,學匯編的記得保重身體啊…..

3匯編過程  

這一步就可以得到.o目標文件了。過程由匯編器as執行,把上面得到的hellow.s文件裡的匯編指令逐條翻譯成機器碼。

g++ -C hellow.s -o hellow.o

4鏈接過程  

由鏈接器ld完成,把多個.o的機器碼鏈接成.out這樣的可執行文件(當然後綴名不是重點)。注意,我這裡的只有一個.cpp文件,所以就只有一個.o文件,不需要鏈接,這只是示例,但是正常工程下肯定不止這一個文件,那時候就要鏈接成可執行文件才可以運行了。

以上是Linux平台裡的示例,你可以在windows下使用g++做上面同樣的步驟。但作為程序猿,建議你使用linux做開發,不要問為什麼,可以找我博客裡關於linux的文章看看。   第一篇就討論到這裡吧,下次更新再討論其它問題。

 

 歡迎訪問本人網站:http://www.programfish.com

LinuxCoder 社區: http://linuxcoder.org

注意:轉載請注明 “作者:廣州Linux愛好者+雲計算 刁金明”

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved