程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言程序編譯過程

C語言程序編譯過程

編輯:關於C

最近在編譯DM8168的ARM端程序時經常出現未定義、重定義等報錯,由於源碼文件多,包含關系比較多,所以自己添加時容易亂。深深的體會到,好的代碼風格是如此重要,之前也在看代碼重構,以後應該更加注意代碼的質量。經思考總結規律如下:

1、公用的數據結構等寫為一個頭文件,其他源文件包含此頭文件。同時為了讓不同源文件裡的函數都可以使用,公用的函數可以放在此頭文件中聲明。

2、其他源文件裡聲明的變量,如果想在另一個文件裡用,需要extern聲明,這樣可以避免各種全局變量的交互混雜。

理解的比較淺,希望高人指點。

下面附上gcc的編譯過程:

以GCC編譯hellworld為例,簡單總結如下。

hello.c源代碼如下:

#include
int main()
{
printf(“Hello, world.\n”);
return 0;
}

通常我們使用gcc來生成可執行程序,命令為:gcc hello.c,默認生成可執行文件a.out

其實編譯(包括鏈接)的命令:gcc hello.c 可分解為如下4個大的步驟:

· 預處理(Preprocessing)

· 編譯(Compilation)

· 匯編(Assembly)

· 鏈接(Linking)

1. 預處理(Preprocessing)

預處理的過程主要處理包括以下過程:

將所有的#define刪除,並且展開所有的宏定義
處理所有的條件預編譯指令,比如#if #ifdef #elif #else #endif等
處理#include 預編譯指令,將被包含的文件插入到該預編譯指令的位置。
刪除所有注釋 “//”和”/* */”.
添加行號和文件標識,以便編譯時產生調試用的行號及編譯錯誤警告行號。
保留所有的#pragma編譯器指令,因為編譯器需要使用它們


通常使用以下命令來進行預處理:

gcc -E hello.c -o hello.i

參數-E表示只進行預處理 或者也可以使用以下指令完成預處理過程

cpp hello.c > hello.i /* cpp - The C Preprocessor */

直接cat hello.i 你就可以看到預處理後的代碼

2. 編譯(Compilation)

編譯過程就是把預處理完的文件進行一系列的詞法分析,語法分析,語義分析及優化後生成相應的匯編代碼。

$gcc –S hello.i –o hello.s

或者

$ /usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c

注:現在版本的GCC把預處理和編譯兩個步驟合成一個步驟,用cc1工具來完成。gcc其實是後台程序的一些包裝,根據不同參數去調用其他的實際處理程序,比如:預編譯編譯程序cc1、匯編器as、連接器ld

可以看到編譯後的匯編代碼(hello.s)如下:

.file "hello.c"

.section .rodata

.LC0:

.string "Hello, world."

.text

.globl main

.type main, @function

main:

pushl %ebp

movl %esp, %ebp

andl $-16, %esp

subl $16, %esp

movl $.LC0, (%esp)

call puts

movl $0, %eax

leave

ret

.size main, .-main

.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"

.section .note.GNU-stack,"",@progbits

3. 匯編(Assembly)

匯編器是將匯編代碼轉變成機器可以執行的命令,每一個匯編語句幾乎都對應一條機器指令。匯編相對於編譯過程比較簡單,根據匯編指令和機器指令的對照表一一翻譯即可。

$ gcc –c hello.c –o hello.o

或者

$ as hello.s –o hello.co

由於hello.o的內容為機器碼,不能以普通文本形式的查看(vi 打開看到的是亂碼)。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved