電子商務(wù)網(wǎng)站建設(shè)的相關(guān)流程八零云自助建站免費(fèi)建站平臺
我們在vs編譯器中寫的代碼按下ctrl f5就可以直接運(yùn)行起來,并且會將運(yùn)行的結(jié)果顯示到顯示器上,這里看上去只有一個步驟但實際上這里會存在很多的細(xì)節(jié),比如說生成結(jié)果在這里插入代碼片
之前我們的代碼會經(jīng)過預(yù)處理,編譯,匯編,鏈接的過程,不同的過程會對應(yīng)不同的操作,那么接下來我們就會一個一個的介紹這些操作所對應(yīng)的操作。
預(yù)處理
程序運(yùn)行的第一步就是預(yù)處理,預(yù)處理的目的就是:將頭文件展開,去掉注釋,宏替換,刪除條件編譯,比如說我們創(chuàng)建一個臨時文件test.c:
并且在這個文件里面輸入一些內(nèi)容:
1 #include<stdio.h> 2 #define NUM_A 20 3 #define NUM_B 30 4 int main()5 {6 #ifdef add7 printf("相加的結(jié)果為:%d\n",NUM_A+NUM_B);//計算相加的結(jié)果8 #else9 printf("相減的結(jié)果為:%d\n",NUM_A-NUM_B);//計算相減的結(jié)果 10 #endif 11 return 0; 12 }
然后我們就退出并且保存這個文件:
到這里我們的準(zhǔn)備工作就完成了。平時我們運(yùn)行文件使用的指令是:gcc test.c
使用這個指令會自動的生成一個文件叫a.out,并且這個文件是一個可執(zhí)行程序,我們運(yùn)行一下這個程序就可以可以看到我們的屏幕上面出現(xiàn)了上面代碼的運(yùn)行的結(jié)果:
但是這里有個問題,使用這個指令我們看不到預(yù)處理的結(jié)果它直接變成了可執(zhí)行程序,所以得在這個指令里面添加一個-E選項,這個選項的功能就是從重現(xiàn)在開始進(jìn)行程序的翻譯,將程序的預(yù)處理執(zhí)行完后就停下來,所以使用這個選項我們就可以看到代碼經(jīng)過預(yù)處理之后的結(jié)果,那么這里的指令就是這樣:gcc -E test.c
執(zhí)行的結(jié)果如下:
我們可以看到這里出現(xiàn)很多亂七八糟的內(nèi)容,那是因為這個指令將執(zhí)行的結(jié)果全部都打印到屏幕上了,由于內(nèi)容很多就顯得很亂,不好查看,所以這里我們還可以在這個指令里面添加一個-o選項,這個選項的功能就是將指令的運(yùn)行的結(jié)果放到一個文件里面,在-o的后面加上你要放的文件,如果這個文件不存在的話,這個指令會自動生成對應(yīng)的文件,比如說我們將上面的指令修改成這樣:gcc -E test.c -o test.i
當(dāng)前目錄下是沒有test.i這個文件的,所以使用這個指令后我們會自動的生成test.i這個文件:
并且這個文件里面裝的內(nèi)容就是之前顯示在屏幕上的內(nèi)容:
我們可以使用vs指令將test.c文件顯示在屏幕上進(jìn)行對比:
我們使用shift+g將右邊屏幕的光標(biāo)移動到最后一行:
我們可以看到在test.i文件的最后出現(xiàn)了test.c文件中的大致內(nèi)容,但是卻略有不同這是test.i的相關(guān)內(nèi)容:
這是test.c的全部內(nèi)容:
仔細(xì)的觀察一下我們可以看到有以下幾點(diǎn)的不同:
- test.c中的2 3 行定義的宏被刪除了。
- test.c中的7 9行的注釋被刪除了。
- test.c中的7 9行中使用的宏被替換成了我們定義的值也就是說NUM_A替換成了20,NUM_B替換成了30。
- test.c中沒有被執(zhí)行的條件編譯被刪除了也就是第6 7 8 10行的內(nèi)容被刪除了。
- test.c中的頭文件被刪除了但是在test.i中出現(xiàn)了更多雜七雜八的東西,所以在預(yù)編譯的過程中將頭文件中的內(nèi)容加載到test.i的文件里面。
那么這就是預(yù)編譯所做的一些操作將頭文件展開,去掉注釋,宏替換,刪除條件編譯,那么這里大家要注意的一點(diǎn)就是在linux操作系統(tǒng)中文件的后綴是沒有意義的,也就是說這里的后綴i對于操作系統(tǒng)來說是沒有什么特殊意義的,但是這個后綴對我們使用者來說卻有很多的意義,比如說我們看到了一個文件的后綴是i就可以想到這個文件是經(jīng)過預(yù)處理后生成的文件,所以大家在執(zhí)行這些操作生成文件的時候還是要將后綴寫成對應(yīng)的形式以免混淆別人,那么上面就是預(yù)處理要干的事情。
編譯
經(jīng)歷完預(yù)處理之后要執(zhí)行的操作就是編譯,編譯要干的事情就是將c語言翻譯成匯編語言,那么這里要執(zhí)行的指令就是:gcc -S test.i -o test.s
那么這里-S選項的作用就是從現(xiàn)在開始進(jìn)行程序的翻譯,將匯編工作完成之后工作就停止,后面加了一個-o選項,所以這里會將執(zhí)行完之后的結(jié)果放到test.s這個文件里面,執(zhí)行完這個指令我們就可以看到這里自動的生成了一個test.s文件,在這個文件里面有我們好多我們看不懂的內(nèi)容:
雖然下面的內(nèi)容我們看不懂,但是可以知道的一件事就是這個test.o文件里面的內(nèi)容是匯編語言:
我們知道計算器能夠識別的語言是二進(jìn)制語言,而test.o文件里面裝的是匯編語言,所以這里的test.o文件無法被運(yùn)行。
匯編
通過上面的講解我們知道編譯是將c語言翻譯成匯編語言,那么這里的匯編要干的事情就是將生成的匯編語言翻譯二進(jìn)制語言,那么這里需要的指令就是:gcc -c test.s -o test.o
,-c選項的作用就是從現(xiàn)在開始進(jìn)行翻譯,將文件中的匯編語言翻譯成二進(jìn)制語言就停止,比如說下面的操作:
這里就自動生成一個test.o文件,我們打開這個文件就可以看到文件中的內(nèi)容就變成了各種奇奇怪怪的符號:
這就是文件經(jīng)過匯編之后的結(jié)果,那么這時肯定會有小伙伴想啊,既然這個文件的內(nèi)容是二進(jìn)制的話,我們是不是就可以運(yùn)行這個文件呢?那么這里可以試一下看看能不能運(yùn)行
結(jié)果很明顯這個文件是無法運(yùn)行的,原因也非常的簡單因為我們上述的三個過程(預(yù)處理 編譯 匯編)所干的事情是翻譯的過程,也就是把你的代碼進(jìn)行修剪然后翻譯成二進(jìn)制文件,但是這里有個問題就是你的代碼里面用了很多別人的函數(shù),你沒有在這個文件里面實現(xiàn)這些函數(shù),比如說printf函數(shù),scanf函數(shù),main函數(shù)等等,這些函數(shù)你都沒有實現(xiàn),雖然你包含了頭文件stdio.h,但是這個文件里面只有這些函數(shù)的聲明,沒有這些實現(xiàn),所以將我們的代碼翻譯成二進(jìn)制文件還是無法滿足運(yùn)行的需求,所以這里我們還得進(jìn)行下一步鏈接。
鏈接
鏈接干的事情就是把我們自己寫的代碼代碼和c標(biāo)準(zhǔn)庫的代碼合并起來,這個標(biāo)準(zhǔn)庫里面裝的就是各種c語言函數(shù)的具體實現(xiàn)等等,所以當(dāng)二進(jìn)制文件經(jīng)過鏈接后,里面使用的函數(shù)就有了具體的實現(xiàn),就可以正常的被執(zhí)行了,那么這里的用的之指令就是:gcc test.o
這里我們不使用-o選項的話,這里就會自動生成一個名為a.out的可執(zhí)行程序,當(dāng)然這里我們也可以人為的生成一個可執(zhí)行程序,那么這里就得加上一個-o選項,那么這里的指令就是:gcc test.o -o mytest
當(dāng)生成完可執(zhí)行程序之后就可以運(yùn)行以下這里的可執(zhí)行文件:
那么上述就是這篇文章的全部內(nèi)容希望大家可以理解謝謝。