您好,登錄后才能下訂單哦!
本篇文章為大家展示了怎么編譯c語言,代碼簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
gcc命令其實依次執(zhí)行了四步操作:1.預(yù)處理(Preprocessing), 2.編譯(Compilation), 3.匯編(Assemble), 4.鏈接(Linking)。
為了下面步驟講解的方便,我們需要一個稍微復(fù)雜一點的例子。假設(shè)我們自己定義了一個頭文件mymath.h,實現(xiàn)一些自己的數(shù)學(xué)函數(shù),并把具體實現(xiàn)放在mymath.c當(dāng)中。然后寫一個test.c程序使用這些函數(shù)。程序目錄結(jié)構(gòu)如下:
├── test.c └── inc ├── mymath.h └── mymath.c
程序代碼如下:
// test.c #include <stdio.h> #include "mymath.h"// 自定義頭文件 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
頭文件實現(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ù)處理之后得到的仍然是文本文件,但文件體積會大很多。gcc的預(yù)處理是預(yù)處理器cpp來完成的,你可以通過如下命令對test.c進行預(yù)處理:
gcc -E -I./inc test.c -o test.i
或者直接調(diào)用cpp命令
$ cpp test.c -I./inc -o test.i
上述命令中-E是讓編譯器在預(yù)處理之后就退出,不進行后續(xù)編譯過程;-I指定頭文件目錄,這里指定的是我們自定義的頭文件目錄;-o指定輸出文件名。
經(jīng)過預(yù)處理之后代碼體積會大很多:
X 文件名 文件大小 代碼行數(shù)
預(yù)處理前 test.c 146B 9
預(yù)處理后 test.i 17691B 857
預(yù)處理之后的程序還是文本,可以用文本編輯器打開。
2.編譯(Compilation)
這里的編譯不是指程序從源文件到二進制程序的全部過程,而是指將經(jīng)過預(yù)處理之后的程序轉(zhuǎn)換成特定匯編代碼(assembly code)的過程。編譯的指定如下:
$ gcc -S -I./inc test.c -o test.s
上述命令中-S讓編譯器在編譯之后停止,不進行后續(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,"",@progbits
3.匯編(Assemble)
匯編過程將上一步的匯編代碼轉(zhuǎn)換成機器碼(machine code),這一步產(chǎn)生的文件叫做目標(biāo)文件,是二進制格式。gcc匯編過程通過as命令完成:
$ as test.s -o test.o
等價于:
gcc -c test.s -o test.o
這一步會為每一個源文件產(chǎn)生一個目標(biāo)文件。因此mymath.c也需要產(chǎn)生一個mymath.o文件
4.鏈接(Linking)
鏈接過程將多個目標(biāo)文以及所需的庫文件(.so等)鏈接成最終的可執(zhí)行文件(executable file)。
命令大致如下:
$ ld -o test.out test.o inc/mymath.o ...libraries...
結(jié)語
經(jīng)過以上分析,我們發(fā)現(xiàn)編譯過程并不像想象的那么簡單,而是要經(jīng)過預(yù)處理、編譯、匯編、鏈接。盡管我們平時使用gcc命令的時候沒有關(guān)心中間結(jié)果,但每次程序的編譯都少不了這幾個步驟。也不用為上述繁瑣過程而煩惱,因為你仍然可以:
$ gcc hello.c # 編譯
$ ./a.out # 執(zhí)行
上述內(nèi)容就是怎么編譯c語言,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。