#define 指示詞 (C/C++)
#define 會 建立宏 ,這是識別碼或參數化識別碼與權杖字串的關聯。 定義巨集之後,編譯器就可以使用語彙基元字串替代原始程式檔中出現的每個識別項。
語法
#define識別碼token-字串opt
#define識別碼(identifieropt, ...,識別碼opt)token-字串opt
備註
#define 指示詞會導致編譯器以權杖字串 取代 來源檔案中每個出現的 識別碼 。 只有在識別碼 形成權杖時,才會取代識別碼。 也就是說, 如果識別碼 出現在批註、字串中,或做為較長識別碼的一部分,則不會取代識別碼。 如需詳細資訊,請參閱 權杖 。
Token-string 引數是由一系列標記所組成,例如關鍵字、常數或完整語句。 一或多個空白字元必須分隔 權杖字串 與 識別碼 。 這個空白不會視為替代文字的一部分,也不是接在上一個文字語彙基元之後的任何空白。
#define
沒有 權杖字串 的 會從來源檔案中移除識別碼的 出現次數。 識別碼 會維持定義,而且可以使用 和 #ifdef
指示詞進行測試 #if defined
。
第二個語法形式會定義類似函式且具有參數的巨集。 這種形式可接受選擇性參數清單,但必須以括號括住。 定義宏之後,每個後續出現的 identifier( identifier opt , ..., identifier opt ) 會取代為 Token-string 引數的版本 ,其實際引數會取代為正式參數。
正式參數名稱會出現在 Token-string 中 ,以標記實際值取代的位置。 每個參數名稱都可以在權杖字串 中 出現多次,而且名稱可以依任何順序顯示。 呼叫中引數的數目必須與巨集定義中參數的數目相符。 盡量使用括號可確保正確解譯複雜的實際引數。
清單中的型式參數是以逗號分隔。 清單中的每個名稱都必須是唯一的,而且清單必須以括號括住。 沒有空格可以分隔 識別碼 和左括弧。 使用行串連 — 將反斜線 ( \
) 放在分行符號的正前 — 在多個來源行上使用 long 指示詞。 正式參數名稱的範圍延伸至結束 Token-string 的新行。
如果已在第二種語法形式中定義巨集,則後面接著引數清單的後續文字執行個體會表示巨集呼叫。 原始程式檔中識別碼 實例 後面的實際引數會與巨集定義中的對應型式參數相符。 Token-string 中的每個 正式參數前面未加上字串化 ()、字元化 ( #@
#
), 或標記貼上 ( ##
) 運算子,或不是後面 ##
接著運算子,都會由對應的實際引數取代。 實際引數中的所有巨集都會在指示詞取代型式參數之前展開。 (運算子描述于 預處理器運算子 。)
下列具有引數的宏範例說明 #define 語法的第 二種形式:
// Macro to define cursor lines
#define CURSOR(top, bottom) (((top) << 8) | (bottom))
// Macro to get a random integer with a specified range
#define getrandom(min, max) \
((rand()%(int)(((max) + 1)-(min)))+ (min))
具有副作用的引數有時會造成巨集產生未預期的結果。 指定的正式參數可能會在 Token-string 中 出現一次以上。 如果以具有副作用的運算式取代該型式參數,則運算式連同其副作用可能會經過多次求值。 (請參閱下方 的範例Token-Pasting Operator (##) .
#undef
指示詞會導致識別碼的前置處理器定義遭到忽略。 如需詳細資訊,請參閱 #undef 指示詞 。
如果所定義的宏名稱發生在 Token-string 中(即使因為另一個宏擴充的結果),它也不會展開。
具有相同名稱之宏的第二 個 #define 會產生警告,除非第二個權杖序列與第一個標記序列相同。
Microsoft 特定的
如果新定義與原始定義在語法上相同,Microsoft C/C++ 可讓您重新定義巨集。 換句話說,這兩個定義可以有不同的參數名稱。 此行為與 ANSI C 不同,這需要兩個定義在語彙上相同。
例如,下列兩個巨集除了參數名稱之外完全相同。 ANSI C 不允許進行這類重新定義,但 Microsoft C/C++ 會編譯它,而不會發生錯誤。
#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( a1 * a2 )
另一方面,下列兩個巨集不相同,而且將會在 Microsoft C/C++ 中產生警告。
#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( b1 * b2 )
END Microsoft 特定的
此範例說明 #define 指示詞:
#define WIDTH 80
#define LENGTH ( WIDTH + 10 )
第一個陳述式會將識別項 WIDTH
定義為整數常數 80,並根據 LENGTH
定義 WIDTH
和整數常數 10。 出現的每個 LENGTH
都會由 (WIDTH + 10
) 取代。 然後出現的每個 WIDTH + 10
都會依序由運算式 (80 + 10
) 取代。 WIDTH + 10
前後的括號很重要,因為括號可用於控制陳述式中的解譯方式,如下所示:
var = LENGTH * 20;
在前置處理階段之後,陳述式會變成:
var = ( 80 + 10 ) * 20;
該陳述式的判斷值為 1800。 若沒有括號,則結果為:
var = 80 + 10 * 20;
評估為 280。
Microsoft 特定的
使用 /D 編譯器選項定義宏和常數的效果與在檔案開頭使用 #define 前置處理指示詞相同。 使用 /D 選項最多可以定義 30 個巨集。
END Microsoft 特定的
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應