十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本篇文章為大家展示了怎么編譯c語言,代碼簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括桑日網(wǎng)站建設(shè)、桑日網(wǎng)站制作、桑日網(wǎng)頁制作以及桑日網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,桑日網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到桑日省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
gcc命令其實(shí)依次執(zhí)行了四步操作:1.預(yù)處理(Preprocessing), 2.編譯(Compilation), 3.匯編(Assemble), 4.鏈接(Linking)。

為了下面步驟講解的方便,我們需要一個(gè)稍微復(fù)雜一點(diǎn)的例子。假設(shè)我們自己定義了一個(gè)頭文件mymath.h,實(shí)現(xiàn)一些自己的數(shù)學(xué)函數(shù),并把具體實(shí)現(xiàn)放在mymath.c當(dāng)中。然后寫一個(gè)test.c程序使用這些函數(shù)。程序目錄結(jié)構(gòu)如下:
├── test.c
└── inc
├── mymath.h
└── mymath.c程序代碼如下:
// test.c #include#include "mymath.h"http:// 自定義頭文件 int main(){ int a = 2; int b = 3; int sum = add(a, b); printf("a=%d, b=%d, a+b=%d\n", a, b, sum); }
頭文件定義:
// mymath.h #ifndef MYMATH_H #define MYMATH_H int add(int a, int b); int sum(int a, int b); #endif
頭文件實(shí)現(xiàn):
// mymath.c
int add(int a, int b){
return a+b;
}
int sub(int a, int b){
return a-b;
}1.預(yù)處理(Preprocessing)
預(yù)處理用于將所有的#include頭文件以及宏定義替換成其真正的內(nèi)容,預(yù)處理之后得到的仍然是文本文件,但文件體積會(huì)大很多。gcc的預(yù)處理是預(yù)處理器cpp來完成的,你可以通過如下命令對(duì)test.c進(jìn)行預(yù)處理:
gcc -E -I./inc test.c -o test.i
或者直接調(diào)用cpp命令
$ cpp test.c -I./inc -o test.i
上述命令中-E是讓編譯器在預(yù)處理之后就退出,不進(jìn)行后續(xù)編譯過程;-I指定頭文件目錄,這里指定的是我們自定義的頭文件目錄;-o指定輸出文件名。
經(jīng)過預(yù)處理之后代碼體積會(huì)大很多:
X 文件名 文件大小 代碼行數(shù)
預(yù)處理前 test.c 146B 9
預(yù)處理后 test.i 17691B 857
預(yù)處理之后的程序還是文本,可以用文本編輯器打開。
2.編譯(Compilation)
這里的編譯不是指程序從源文件到二進(jìn)制程序的全部過程,而是指將經(jīng)過預(yù)處理之后的程序轉(zhuǎn)換成特定匯編代碼(assembly code)的過程。編譯的指定如下:
$ gcc -S -I./inc test.c -o test.s
上述命令中-S讓編譯器在編譯之后停止,不進(jìn)行后續(xù)過程。編譯過程完成后,將生成程序的匯編代碼test.s,這也是文本文件,內(nèi)容如下:
// test.c匯編之后的結(jié)果test.s
.file "test.c"
.section .rodata
.LC0:
.string "a=%d, b=%d, a+b=%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
movl $2, 20(%esp)
movl $3, 24(%esp)
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl 20(%esp), %eax
movl %eax, (%esp)
call add
movl %eax, 28(%esp)
movl 28(%esp), %eax
movl %eax, 12(%esp)
movl 24(%esp), %eax
movl %eax, 8(%esp)
movl 20(%esp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits3.匯編(Assemble)
匯編過程將上一步的匯編代碼轉(zhuǎn)換成機(jī)器碼(machine code),這一步產(chǎn)生的文件叫做目標(biāo)文件,是二進(jìn)制格式。gcc匯編過程通過as命令完成:
$ as test.s -o test.o
等價(jià)于:
gcc -c test.s -o test.o
這一步會(huì)為每一個(gè)源文件產(chǎn)生一個(gè)目標(biāo)文件。因此mymath.c也需要產(chǎn)生一個(gè)mymath.o文件
4.鏈接(Linking)
鏈接過程將多個(gè)目標(biāo)文以及所需的庫文件(.so等)鏈接成最終的可執(zhí)行文件(executable file)。
命令大致如下:
$ ld -o test.out test.o inc/mymath.o ...libraries...
結(jié)語
經(jīng)過以上分析,我們發(fā)現(xiàn)編譯過程并不像想象的那么簡(jiǎn)單,而是要經(jīng)過預(yù)處理、編譯、匯編、鏈接。盡管我們平時(shí)使用gcc命令的時(shí)候沒有關(guān)心中間結(jié)果,但每次程序的編譯都少不了這幾個(gè)步驟。也不用為上述繁瑣過程而煩惱,因?yàn)槟闳匀豢梢裕?/p>
$ gcc hello.c # 編譯
$ ./a.out # 執(zhí)行
上述內(nèi)容就是怎么編譯c語言,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。