關於C檔案預處理的理解

2021-07-23 18:52:45 字數 3046 閱讀 9100

1.預定義符號

2.巨集和函式的區別

3.理解編譯鏈結的整個過程和詳細的每個過程

一、預定義符號

這些符號的值可以給我們提供一些編譯c程式檔案時的資訊,給我們除錯或建立日誌檔案提供便利。

以下是對一些預定義符號的具體描述:

_file_   :提供當前進行編譯的源檔名

_line_  :提供檔案當前行的行號

_date_ :提供檔案編譯時的日期

_time_  :提供檔案編譯時的時間

_stdc_ :如果編譯器遵循ansi c,其值則為1,否則為未定義。

<

ansi c:

美國國家標準協會(american national standards institute)制定的乙個c語言的標準

>

以下是**實現:

二、巨集和函式的區別

(其中內容借鑑了《c和指標》一書中的描述)

#define就是預處理巨集定義命令,它可以定義乙個符號代替乙個常量或是乙個文字,以後在c檔案的書寫中,就可以使用這個符號來代替這些常量或 操作,減少程式設計師的工作量。

函式對於我來說,就像是乙個盒子,它裡面封裝這完成一些功能的語句,我們可以通過在主函式中呼叫函式的名稱來使用函式裡面封裝的內容。

這裡根據《c和指標》中的描述,函式和巨集主要 存在5方面的區別:

1.**長度:

對於巨集來說,因為在c檔案的預處理過程中,編譯器會掃瞄巨集所定義的符號,並用其所代表的內容來替換原來的符號,所以除了用一些特別短小巨集定義外,其他的巨集替換會導致程式的長度大大增加。

對於函式而言,卻完全不用擔心這樣的事發生,函式的**只存在於乙個地方,而其他地方要使用時,都是使用函式名來呼叫這個函式。所以,不會增加**的長度。

2.執行速度

對於巨集來說,它是在預處理階段就直接被所定義的內容所替換,在後面的編譯階段就直接執行,基本沒有開銷了。所以巨集的執行速度快。

對於函式來說,函式的執行是通過在棧上開闢臨時空間,進行函式體的操作,然後執行完函式後銷毀。這些操作都會造成開銷。所以函式的執行速度要慢於巨集。

3.操作符優先順序

對於巨集來說,巨集引數的求值是在所有周圍的表示式的上下文環境裡,它的引數如果不帶括號就預設和周圍的操作融為一體。這樣如果巨集裡定義的運算子的優先順序低於其周圍環境裡的,則會出現不可預知的後果。

例如:

解釋:上面函式的列印輸出並沒有按我們預想的結果輸出了25,而是輸出了13,這就是由於運算子優先順序的問題。在檔案的預處理階段,程式中printf語句會被替換成printf(「%\n」,5*2+3);//不是5*(2+3)

4.引數求值

對於巨集來說,引數每次用於巨集定義時,都會被重新求值,所以這些引數都具有***,而它們的出現將使程式出現不可預知的結果。

對於函式來說,引數只是在函式呼叫前求值一次,在函式中多次使用引數並不會使引數被求值多次,所以不會導致函式的返回值不可預知。

5.引數型別

對於巨集來說,它的引數與型別無關,可以表示變數名,也可以表示型別名。

對於函式來說,它的引數必須指定具體的型別。對於實現相同的功能,函式的引數型別不同,則需定義不同的函式。

三、理解編譯鏈結的整個過程和詳細的每個過程

主要流程:

c語言源程式—預處理—>匯程式設計序—彙編—>二進位制目標程式—鏈結—>可執行程式

預處理階段:

1.預處理主要由預處理器完成。這一階段一共完成4件事。

1)標頭檔案的展開:將程式中所用的標頭檔案用其內容來替換頭檔名。

2)巨集替換:掃瞄程式中的符號,將其 替換成巨集所定義的內容。

3)去掉注釋:去掉程式中的注釋。

4)條件編譯:在程式中難免會有檔案的重複引用,如果每次引用都要重新呼叫檔案中的內容,這樣就會增加許多不必要的開銷 。所以為了防止這種情況的發生,我們在檔案中使用條件編譯符號來防止這種情況的發生。

條件編譯語法;

#if  constant-expression

statements

#elif

other statements

#else

other statements

#endlf

測試乙個符號是否被定義:

#ifdef

#ifndef

2.彙編,就是將高階語言轉換成低階的機器語言。

3.鏈結,就是將程式中出現的函式等,與其原始檔進行「匹配連線」,例如實現標準輸入輸出就需要鏈結到庫檔案stdio.h中。因為在程式中我們只是呼叫這些函式,真正的實現還是在庫檔案中。

以下,使用linux中gcc來實現以上過程:

先介紹一些常用命令:

假定我們已經事先建立好了text.c檔案

gcc -e text.c -o text.i  //將.c檔案經預處理後的.i檔案

gcc -s text.i -o text.s  //將.i檔案轉換成組合語言,為.s檔案

gcc -c text.s - o text.o  //將.s檔案轉換成目標檔案(二進位制檔案),為.o檔案

原始檔:

預處理:

編譯:

執行程式:

關於預處理

1.能用巨集定義開始或者結束一段注釋嗎?例如 define bsc define bmc define emc 那麼 bsd my single line comment bmc my single line comment emc 正確嗎?答案是不正確的,這是因為 注釋先於預處理指令被處理 當這兩...

C 的預處理

預處理是乙個處理和管理文字型原始檔的程式。通常被編譯器作為編譯處理的第一步所呼叫。預處理的工作過程叫做轉換,預處理器的工作就是把原始檔的文字分成一些標記。這些文字形式的標記用來定位預處理指令。當把乙個原始檔編譯前,預處理經過以下4步 1 字元對映 把所有原始檔字元轉化成內部方法表示的字串行。2 行結...

c 預處理和預處理命令

預處理發生在編譯之前,預處理輸出的是乙個單一的檔案,這個檔案被送到編譯器,進行編譯。每條預處理命令都控制預處理器的行為。每條預處理命令佔據一行,有以下的格式 character 預處理命令 one of define,undef,include,if,ifdef,ifndef,else,elif,e...