對編譯連結的整個過程和詳細的每個過程的認識
在windows下的開發環境是整合開發環境,編譯連結過程一鍵就可做到,而在linux下的操作都是離散的,對於編譯連結的認識是建立在linux環境基礎之上的;電腦只能識別二進位制序列,而我們的程式碼是利用c語言寫的,需要轉換位機器所能識別的二進位制序列,編譯連結過程就是將程式碼轉換成機器所能識別的二進位制序列(目標檔案)並生成可執行檔案的過程。
整個過程為:
1.預處理
在此步驟對程式碼進行預處理:標頭檔案展開,巨集替換,去註釋,條件編譯;
gcc -E test.c -o test.i
此命令是對test.c進行到預處理,並將處理結果放到test.i中。
2.c程式碼轉換為彙編;
gcc -S test.i -o tets.s
此命令是對test.i進行彙編轉換,並將彙編轉換結果放入test.s中。
3.彙編——>二進位制;
gcc -c test.s -o test.o
此處test.o是目標檔案,其中存放的是二進位制序列;
4.連結
連結所有二進位制程式,生成可執行檔案。
標頭檔案展開:展開為標頭檔案所在的絕對地址,在linux下#include<stdio.h>展開為"/usr/include/stdio.h"
巨集替換:出現巨集識別符號的位置,替換為其定義式識別符號後面的文字;
例:
替換後為:#define PRINT printf("Replace\n") int main() { PRINT; return 0; }
#include<stdio.h>
#define PRINT printf("Replace\n")
int main()
{
PRINT;
return 0;
}
去註釋:在預處理階段,相當於直接將註釋的這部分程式碼剔除掉,不出現在test.i檔案中;
條件編譯:
在編譯程式時,使用條件編譯可以實現某條語句或某組語句進行編譯或者忽略;條件編譯常常用於除錯程式;
條件編譯的基本結構為:
#if 常量表達式
語句;
#endif
和if語句一樣也可以巢狀使用
如果常量表達式的值為非零值(真),正常執行語句部分,否則這部分就像去掉註釋掉一樣,不出現在檔案中;
#ifdef MIN
語句;
#endif
如果MIN這個巨集已被定義就執行語句部分,如果沒有定義,就刪除語句部分(即這部分不進行編譯);
例:
#include<stdio.h>
//#define DEBUG
int main()
{
#ifdef DEBUG
printf("DEBUG\n");
#endif
return 0;
}
DEBUG沒有被定義,在預處理時,將printf();語句刪除,即下面這樣:
int main()
{
return 0;
}
若定義了DEBUG這個巨集,在預處理後為:
int main()
{
printf("DEBUG\n");
return 0;
}