久久久国产精品视频袁燕,99re久久精品国产,亚洲欧美日韩国产综合v,天天躁夜夜躁狠狠久久,激情五月婷婷激情五月婷婷

C語言中宏展開規(guī)則,你知多少?

1. 宏展開規(guī)則unsetunset

在C語言預處理器中,如果宏參數(shù)本身是一個宏,其展開時機遵循一定的規(guī)則。具體來說,宏參數(shù)的展開時機取決于它在宏定義中的位置和使用方式。以下是詳細的規(guī)則和解釋:

宏參數(shù)的展開時機

當宏被調(diào)用時,預處理器會按照以下步驟處理宏參數(shù):

參數(shù)替換

  • 在宏調(diào)用時,預處理器會將宏參數(shù)替換為實際參數(shù)。
  • 如果宏參數(shù)本身是一個宏,預處理器會先展開這個宏參數(shù),然后再進行替換。

替換列表中的宏展開

  • 在替換列表中,預處理器會逐個處理每個符號。如果符號是一個宏,預處理器會進一步展開這個宏。
  • 但是,如果符號是一個宏參數(shù),并且這個宏參數(shù)在替換列表中被用作###操作符的參數(shù),則不會展開這個宏參數(shù)。

具體規(guī)則

  • 參數(shù)展開優(yōu)先于替換列表展開:宏參數(shù)在替換到替換列表之前會被展開。
  • 替換列表中的宏展開:替換列表中的符號(包括展開后的參數(shù))會被進一步展開,除非它們被用作###操作符的參數(shù)。

示例

示例1:參數(shù)展開優(yōu)先

假設我們有以下宏定義:

#define A 123#define PRINT(x) printf("%d\n", x)

調(diào)用宏:

PRINT(A);

展開過程:

  1. 參數(shù)替換A 是一個宏,預處理器先展開 A,得到 123

  2. 替換列表展開:將 123 替換到 PRINT 的替換列表中,得到:

    printf("%d\n", 123);

最終輸出:

123

示例2:參數(shù)不展開(#操作符)

假設我們有以下宏定義:

#define A 123#define STRINGIFY(x) #x

調(diào)用宏:

printf("%s\n", STRINGIFY(A));

展開過程:

  1. 參數(shù)替換A 是一個宏,但因為 STRINGIFY 的替換列表中使用了 # 操作符,所以不會展開 A。

  2. 替換列表展開:將 A 替換到 STRINGIFY 的替換列表中,得到:

    printf("%s\n", "A");

最終輸出:

A

示例3:參數(shù)不展開(##操作符)

假設我們有以下宏定義:

#define A 123#define CONCAT(x, y) x##y

調(diào)用宏:

CONCAT(A, B);

展開過程:

  1. 參數(shù)替換A 是一個宏,但因為 CONCAT 的替換列表中使用了 ## 操作符,所以不會展開 A。

  2. 替換列表展開:將 A 和 B 替換到 CONCAT 的替換列表中,得到:

    AB

最終結果:AB 是一個符號,而不是 123B

4. 規(guī)則

  • 參數(shù)展開優(yōu)先:宏參數(shù)在替換到替換列表之前會被展開。
  • 替換列表中的宏展開:替換列表中的符號會被進一步展開,除非它們被用作###操作符的參數(shù)。
  • 特殊情況:如果宏參數(shù)在替換列表中被用作###操作符的參數(shù),則不會展開這個宏參數(shù)。

unsetunset2. 宏參數(shù)不展開的處理方法unsetunset

#define STRINGIFY(x)    STRINGIFY_HELPER(x)#define STRINGIFY_HELPER(x)     #x#define STRINGCAT(x, y)  STRINGCAT_HELPER(x, y)#define STRINGCAT_HELPER(x, y)  x##y

這些規(guī)則確保了宏的展開過程是可預測的,同時也提供了一種靈活的方式來控制宏的行為。

這段代碼中定義了兩個宏 STRINGIFY 和 STRINGIFY_HELPER,以及 STRINGCAT 和 STRINGCAT_HELPER。之所以需要兩個宏來實現(xiàn)功能,而不是用一個宏直接完成,是因為 C 預處理器的工作機制。

原因解釋

  1. 預處理器的展開規(guī)則在 C 預處理器中,宏參數(shù)在第一次展開時不會立即被替換為實際值,而是保留其原始形式。只有通過間接展開(即通過另一個宏調(diào)用)才能正確解析參數(shù)的實際值。

  2. 具體場景分析

    • 對于 STRINGIFY(x),如果直接定義為 #x,則無法正確處理帶參數(shù)的宏或復雜表達式。通過 STRINGIFY_HELPER(x) 的間接調(diào)用,可以確保參數(shù)被正確展開后再進行字符串化。
    • 同理,對于 STRINGCAT(x, y),如果直接定義為 x##y,則無法正確連接帶參數(shù)的宏或復雜表達式。通過 STRINGCAT_HELPER(x, y) 的間接調(diào)用,可以確保參數(shù)被正確展開后再進行拼接。
  3. 示例對比假設有以下代碼:

    #define FOO 123#define STRINGIFY(x)    #x#define STRINGCAT(x, y) x##yconst char* str = STRINGIFY(FOO); // 結果是 "FOO" 而不是 "123"int value = STRINGCAT(FOO, 456);  // 結果是 FOO456 而不是 123456

    如果使用間接宏:

    #define STRINGIFY(x)    STRINGIFY_HELPER(x)#define STRINGIFY_HELPER(x)     #x#define STRINGCAT(x, y)  STRINGCAT_HELPER(x, y)#define STRINGCAT_HELPER(x, y)  x##yconst char* str = STRINGIFY(FOO); // 結果是 "123"int value = STRINGCAT(FOO, 456);  // 結果是 123456

通過間接宏調(diào)用,參數(shù)會被正確展開,從而實現(xiàn)預期的功能。

unsetunset總結unsetunset

定義兩個宏的原因是為了利用 C 預處理器的兩步展開機制,確保宏參數(shù)能夠被正確解析和處理。如果只用一個宏實現(xiàn),則無法正確處理復雜的宏參數(shù)或表達式。

聲明:本內(nèi)容為作者獨立觀點,不代表電子星球立場。未經(jīng)允許不得轉(zhuǎn)載。授權事宜與稿件投訴,請聯(lián)系:editor@netbroad.com
覺得內(nèi)容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關注 37
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧