學習一門語言程序,本人覺得還是得學習它的編譯規則,現在,通過小例子小結下自己對C編譯的認識。
/*test.c 了解C程序的編譯*/#include <stdio.h>int main(void){ printf("Hello World!/n"); return 0;}對于test.c,我們常用一步編譯到位的命令是:
gcc -o test test.c 或者 gcc test.c -o test
實際上,上面的這個編譯命令包含了四個階段的處理,即預處理(也稱預編譯,Preprocessing)、編譯(Compilation)、匯編 (Assembly)和連接(Linking)。
這里詳細列舉完整的編譯過程
預處理:
作用: 預處理的作用主要是讀入源代碼,檢查包含預處理指令的語句和宏定義,并對源代碼進行響應的轉換。預處理過程還會刪除程序中的注釋和多余的空白字符。
對象: 預處理指令是以“#”開頭的,預處理的處理對象主要包括以下方面:
(1)#define 宏定義
(2)#運算符 #運算符作用是把跟在其后的參數轉換成一個字符串。
/***例***/ #define PASTE(n) "adhfkj"#n int main() { printf("%s/n",PASTE(15)); return 0; } /********輸出adhfj15*********/(3)##運算符 ##運算符的作用用于把參數連接到一起。
/*****例*****/ #define NUM(a,b,c) a##b##c #define STR(a,b,c) a##b##c int main() { printf("%d/n",NUM(1,2,3)); printf("%s/n",STR("aa","bb","cc")); return 0; } /*********最后程序的輸出為:aabbcc**********/(4)條件編譯指令
(5)頭文件包含指令
(6)特殊符號
__FILE__包含當前程序文件名的字符串
__LINE__表示當前行號的整數
__DATE__包含當前日期的字符串
__TIME__包含當前的字符串
如上面的test.c文件的預處理指令是
gcc -E test.c -o test.i
編譯-編譯成匯編語言
gcc -S test.i -o test.s
這是上面代碼編譯出來test.s的內容
.file "test.c" .section .rodata.LC0: .string "hello world" .text.globl main .type main, @functionmain:.LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl $.LC0, %edi call puts movl $0, %eax leave .cfi_def_cfa 7, 8 ret .cfi_endproc.LFE0: .size main, .-main .ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-4)" .section .note.GNU-stack,"",@progbits
匯編
作用:將上面的匯編指令編譯生成目標文件
gcc -c test.s -o test.o
這是上面的test.o文件的內容