小豆丁:老張!老張!
老張:幹嘛?
小豆丁:咋啦?愁眉苦臉的,是不是又被媳婦給揍了?
老張:開玩笑,我在家那就是相當於老虎的存在,誰敢揍我!
媳婦:老張,你說啥?我沒聽清,你再說一遍?
老張:我是老虎,你是武松......
小豆丁:哈哈哈...哈哈哈...老張!你又慫了...
老張:要是沒事的話就趕緊給我圓潤的離開!!!
小豆丁:有事有事!嘿嘿,我想問問,啥事可執行程序啊?
老張:就是可以執行的程序。
小豆丁:額...具體說說唄...
老張:哼,不想說!
小豆丁:我錯了,老張,不該笑話你,你就跟我說說吧!
老張:看在你態度還算誠懇的態度上,就跟你說說吧!可執行程序,實際上就是計算機可以執行的指令的集合,我們在電腦上寫好的程序代碼,經過編譯器的編譯,最終形成的就是可執行程序,這樣計算機就可以按照代碼中想要表達的功能進行工作了。
小豆丁:那編譯器是怎麼把代碼編程可執行程序的啊?
老張:這個過程就有點複雜了。我們以Linux作業系統gcc編譯器為例,來看下對C程序的編譯處理過程。
小豆丁:嗯嗯,快講吧,我已經準備好記錄了!
老張:計算機只認識二進位0和1這種文件,而我們寫的C程序顯然不是二進位文件,這就需要編譯器對我們寫好的程序進行編譯,使之變成計算機可以識別的二進位文件,也就是你剛剛所問的可執行程序。從C程序文件到可執行程序,可以分為四個過程。
小豆丁:哪四個過程啊?
老張:第一個就是預處理過程,可以通過gcc編譯器配合用-E選項進行處理,比如下圖,有一個寫好的C語言程序
通過gcc -E hello.c -o hello.i指令,我們可以完成hello.c文件的預處理操作,將預處理操作之後得到的結果保存到hello.i文件中。
小豆丁:那預處理階段編譯器都做什麼工作了。
老張:這個問題問得好,我們可以打開hello.i文件,看看預處理之後的得到的內容,如下圖。
從圖中我們可以看到,代碼有原本的五六行擴充到了八百多行。這是因為在原本程序中,我們通過預處理指令#include包含了頭文件stdio.h,編譯器在預處理過程中會將包含的頭文件替換進我們的程序中,所以看到預處理後文件的代碼量增加很多。
小豆丁:那預處理階段只是進行頭文件的替換嗎?
老張:當然不是了,在預處理階段,除了頭文件的替換之外,還會進行宏替換和條件編譯的處理。
小豆丁:哦哦,我記住了,那第二個階段呢?
老張:第二個階段叫做彙編階段,我們可以通過gcc -S hello.i -o hello.s指令完成操作,將hello.i文件進行彙編處理,將處理後得到的內容存放到hello.s文件中。如下圖
小豆丁:這個階段都做了什麼工作啊?
老張:我們可以打開hello.s文件看下,發現文件內容已經不是C語言的代碼了,在這個階段,編譯器會把我們的代碼轉換成彙編指令,如下圖
小豆丁:是不是從C語言的代碼轉換成彙編指令,計算機就更容易理解和執行了?
老張:你說得對,值得表揚!
小豆丁:哈哈,本豆丁也是很聰明的,勵志要稱為一名優秀的程式設計師!
小豆丁:那第三個階段是什麼啊?
老張:第三個階段是編譯階段,在這個階段編譯器會將彙編文件轉換成二進位文件,我們把轉換後的二進位文件稱為目標文件,可以用gcc -c hello.s -o hello.o指令完成操作,具體如圖。
小豆丁:老張,這個hello.o文件我打開後怎麼看不懂啊,都是亂碼啊?
老張:看不懂是正常的,因為這是個二進位文件,已經不是我們所能理解的代碼範疇內了。
小豆丁:既然這是一個二進位文件,是不是計算機就能理解了?是不是我們就可以執行它了?
老張:還不能,雖然hello.o是一個二進位文件,但是還不能執行,我們還需要最後一步操作,叫做連結,將程序執行過程中需要用到的一些庫和運行時文件連結到hello.o上,形成最終的a.out可執行程序,才能運行。
小豆丁:哦,還要連結庫和相關文件啊,那最後一步怎麼操作啊?
老張:最後一步比較簡單,用gcc hello.o指令就可以,最後會生成可執行程序a.out,這個時候就可以運行了,如下圖。
小豆丁:哦,我懂了,我們寫好的C語言程序,要經過編譯器編譯才能成為可以運行的程序,而這個編譯的過程分為四步,分別是預處理、彙編、編譯和連結,每一步都有自己的功能和作用。
老張:不錯不錯,孺子可教也。
小豆丁:謝謝老張,我走了,趕緊回去敲個代碼試試去!哈哈!
小豆丁:還有啊,沒事不用總惹你媳婦生氣了,看把你揍的!
老張:......
老張:喜歡老張的話,就關注我吧,每天分享一個IT小知識!