預處理指令是以#
號開頭的**行,# 號必須是該行除了任何空白字元外的第乙個字元。# 後是指令關鍵字,在關鍵字和 # 號之間允許存在任意個數的空白字元,整行語句構成了一條預處理指令,該指令將在編譯器進行編譯之前對源**做某些轉換。
部分預處理指令:
指令說明
#空指令,無任何效果
#include
包含乙個源**檔案
#define
定義巨集#undef
取消已定義的巨集
#if如果給定條件為真,則編譯下面**
#ifdef
如果巨集已經定義,則編譯下面**
#ifndef
如果巨集沒有定義,則編譯下面**
#elif
如果前面的#if給定條件不為真,當前條件為真,則編譯下面**
#endif
結束乙個#if……#else條件編譯塊
預處理功能是c語言特有的功能,它是在對源程式正式編譯前由預處理程式完成的,程式設計師在程式中用預處理命令來呼叫這些功能。
使用預處理功能便於程式的修改、閱讀、移植和除錯,也便於實現模組化程式設計。
巨集定義可以帶有引數,巨集呼叫時是以實參代換形參,而不是「值傳送」。
為了避免巨集代換時發生錯誤,巨集定義中的字串應加括號,字串**現的形式引數兩邊也應加括號。
#define非常方便,所以我們當然都喜歡用它。define常用來定義常量和字串常量。例如,#define pi 3.1415926
在後續的**中,你都可以用pi來代替這一串數字了。而且就算我要求pi的精度再提高一些那也沒有關係,我們只要在define處修改一下就可以了。若是沒有使用巨集定義,你就要在**中處處尋找3.1415926然後去修改,是不是感覺痛苦不堪呢?
雖然它可以給我們帶來許多便利,但是在使用它的時候一定要小心再小心,它也經常會在你不注意的時候讓你犯下錯誤。例如下面這段**。
#define pchar char*
pchar p1,p2;
這段**有什麼問題呢?編譯並不會出錯,而且p1確實是char*型別。但是!
照理來說指標再取位址就要用char**型別的變數來接收,所以char**a = &p1這句**並無問題。
但是char**b = &p2提示了錯誤:char*型別的值不能用char**來接受。也就是說我們的p2它竟然是乙個char型別,而並不是char*型別變數?
其實這個地方替換完之後是char *p1,p2,*是跟著p1的,所以p2是char型別。
所以像這種沒有辦法一下就發現的錯誤才是最恐怖的錯誤。像這種情況我還是建議大家乙個個的定義變數。實在不行可以使用typedef,不會出現這種問題。
我們還可以用define定義字串,一般用於路徑:
#define file_path e:\folder1\1.txt
這個預處理命令也就是undefine的意思,即撤銷巨集定義。也就是說巨集定義的生命週期從#define開始到#undef結束。
檔案包含是預處理的乙個重要功能,它可用來把多個原始檔連線成乙個原始檔進行編譯,結果將生成乙個目標檔案。
這是我們最常見的詞語了。在編譯乙個程式的時候,首先第一句話就是#include 啦。它同樣也非常重要,是將多個原始檔連線成乙個原始檔進行編譯,結果就生成乙個目標檔案(obj)。常見有兩種形式:
1、include
用尖括號括起來的標頭檔案一般都是系統自帶的,表示系統將在指定的路徑進行尋找。
2、include "***.h"
雙引號一般則用於我們自己編寫的標頭檔案,系統也會優先在當前目錄中查詢。如果找不到指定檔名的檔案就會和形式1一樣在指定的路徑進行尋找。
條件編譯允許只編譯源程式中滿足條件的程式段,使生成的目標程式較短,從而減少了記憶體的開銷並提高了程式的效率。
平常寫**過程中,我們為了實現分支結構會經常使用if else結構,在預處理同樣也有類似的功能,即條件編譯。我們可以按照不同的條件去編譯不同的部分,這對程式的移植和除錯有著巨大的幫助。條件編譯主要有以下兩種形式。
#ifdef 識別符號1 && #ifndef 識別符號2
//code1
#else
//code2
#endif
這一段就是經典的條件編譯。如果(ifdef)定義了識別符號1 並且 如果沒有定義(ifndef)識別符號2,執行**段code1;否則執行code2.
要注意的是#ifdef或#ifndef需要和#endif對應。
#if 常量表示式
//code1
#else
//code2
#endif
這段則無限接近我們日常使用的if else了。同樣要注意endif。
除此之外還有乙個#elif,即是elseif,形成if else_if 階梯狀語句,可以進行多種編譯選擇。
它的作用人如其名,是用來提示錯誤的,編譯程式時如果遇到#error就會生成乙個編譯錯誤提示資訊並停止編譯。關於提示的錯誤資訊都是系統定義好的。
#pragma可能是所有預處理指令中最複雜的那個了,因為它可以跟很多引數,而這些引數實現的功能也都大相徑庭。當然了,越複雜功能也就越強大,這裡挑幾個常見的引數進行講解。
1.#pragma once
在標頭檔案的最開始處加上這句話,就可以避免標頭檔案的重複引用(include)。它的作用就是保證每個標頭檔案只編譯一次,再加入同名的標頭檔案也沒有關係(反正也不編譯,且不會報錯)。
2.#pragma message
在我們編寫程式時,有時一旦定義了許多巨集則有可能忘記了某個關鍵的巨集是否正確的設定了。這時只需要使用這條指令就可以一目了然。
具體用法:
編譯時的控制台將顯示引號中的內容。
當出現這條語句代表預編譯標頭檔案到此為止,後面的將不再參與預編譯。通常這樣做用來指定編譯優先順序,同時也可以加快鏈結的速度(一次編譯太多頭檔案可能會佔很多磁碟空間)。
4.#pragma warning
此指令用於和warning有關的操作(即非致命程式設計錯誤的警告)。
具體示例:
#pragma warning (disable:4707) //遮蔽4707警告
#pragma warning (once:4706) //只顯示一次4706警告
#pragma warning (error:164) //將164號警告當作乙個錯誤。
也可以三合一寫成:#pragma warning (disable:4707;once:4706;error:164)
5.#pragma comment(備註,注釋)
該指令用於導入庫。
例如:#pragma comment (lib,"user32.lib")
將user32.lib 庫檔案匯入本工程中。
6.#pragma pack
本知識涉及到記憶體對齊。
C語言 預處理命令
我們可以在c源程式中插入傳給編譯程式的各中指令,這些指令被稱為預處理器指令,它們擴充了程式設計的環境。現把常用的預處理命令總結如下 1.預處理程式 按照ansi標準的定義,預處理程式應該處理以下指令 if ifdef ifndef else elif endif define undef line ...
C語言 預處理命令
一 巨集定義 在 語言源程式中允許用乙個識別符號來表示乙個字串,稱為 巨集 被定義為 巨集 的識別符號稱為 巨集名 在編譯預處理時,對程式中所有出現的 巨集名 都用巨集定義中的字串去代換,這稱為 巨集代換 或 巨集展開 巨集定義是由源程式中的巨集定義命令完成的。巨集代換是由預處理程式自動完成的。在 ...
C語言預處理命令
以 開頭的預處理命令。如 include,巨集定義命令 define pi 3.1415926等。在源程式中這些命令都放在函式之外,而且一般放在原始檔前面,它們稱為預處理部分。無參巨集定義 無參巨集的巨集名後不帶引數。其定義的一般形式為 define 識別符號 字串 其中的 表示這是一條預處理命令,...