1. 程式人生 > >對編譯連結的整個過程和詳細的每個過程的認識

對編譯連結的整個過程和詳細的每個過程的認識

在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;

}