性无码一区二区三区在线观看,少妇被爽到高潮在线观看,午夜精品一区二区三区,无码中文字幕人妻在线一区二区三区,无码精品国产一区二区三区免费

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

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

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

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

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

參數(shù)替換

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

替換列表中的宏展開

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

具體規(guī)則

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

示例

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

假設(shè)我們有以下宏定義:

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

調(diào)用宏:

PRINT(A);

展開過程:

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

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

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

最終輸出:

123

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

假設(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ù)不展開(##操作符)

假設(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

最終結(jié)果:AB 是一個符號,而不是 123B。

4. 規(guī)則

  • 參數(shù)展開優(yōu)先:宏參數(shù)在替換到替換列表之前會被展開。
  • 替換列表中的宏展開:替換列表中的符號會被進(jìn)一步展開,除非它們被用作###操作符的參數(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ī)則確保了宏的展開過程是可預(yù)測的,同時也提供了一種靈活的方式來控制宏的行為。

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

原因解釋

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

  2. 具體場景分析

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

    #define FOO 123#define STRINGIFY(x)    #x#define STRINGCAT(x, y) x##yconst char* str = STRINGIFY(FOO); // 結(jié)果是 "FOO" 而不是 "123"int value = STRINGCAT(FOO, 456);  // 結(jié)果是 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); // 結(jié)果是 "123"int value = STRINGCAT(FOO, 456);  // 結(jié)果是 123456

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

unsetunset總結(jié)unsetunset

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

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