热门问题
时间线
聊天
视角

X巨集

来自维基百科,自由的百科全书

Remove ads

X巨集(X macros)是程式語言巨集裡的經典用法,可以產生類似列表的資料結構或是程式結構,常用在列表中部份內容無法用indexing合成的情形(例如在編譯期就要產生)。若要維護列表,其對應項需要以相同的順序聲明或執行,可以用X巨集可靠的維護此部份程式。

這類列表的例如包括陣列的初始化(與枚舉常數和函式原型的聲明一起),敘述序列和switch語句的生成等。

X巨集的使用可以追溯到1960年代[1],在現今的C語言C++語言中仍可使用,但和其他語言特性相比較,知道X巨集的人比較少[2][3]

實現

X巨集包括兩部份:

  1. 列表元素的定義
  2. 列表的展開,產生部份的宣告或是敘述

列表是由巨集或是標頭檔所定義(命名為LIST),本身不會產生程式碼,只包括了一連串巨集(命名為X)列表,巨集會依該順序進行,列表中也包括列表元素的資料。每一個參照列表LIST時,會加上要執行的巨集。列表LIST展開時,會將X改為真正要執行的巨集,該巨集就會針對列表的每一個元素依序處理,產生資料或是程式碼。

範例1

此例中定義一個變數列表,並且可以自動產生其宣告敘述,以及用printf顯示的敘述。

首先是列表定義。列表可以包括多個引數,不過目前只使用變數名稱。

#define LIST_OF_VARIABLES \
    X(value1) \
    X(value2) \
    X(value3)

接著將此列表展開,以此產生變數宣告:

#define X(name) int name;
LIST_OF_VARIABLES
#undef X

用類似的方式,可以產生用prints顯示變數和值的敘述:

void print_variables(void)
{
#define X(name) printf("%s = %d\n", #name, name);
    LIST_OF_VARIABLES
#undef X
}

透過C預處理器,會產生以下的程式碼。其中的換行和縮排是方便閱讀才放上去的,預處理器其實不會產生換行和縮排:

int value1;
int value2;
int value3;

void print_variables(void)
{
    printf("%s = %d\n", "value1", value1);
    printf("%s = %d\n", "value2", value2);
    printf("%s = %d\n", "value3", value3);
}
Remove ads

範例2,用X巨集為參數

此範例設法提高X巨集的可讀性:

  1. 定義列表的巨集名稱前面加上FOR_。
  2. 將工作巨集以參數方式傳遞給列表巨集。一方面可以避免定義一個名稱無法表示用途的巨集X,也避免後續需要undefine該巨集。
  3. 使用可變參數巨集...的語法在工作巨集中,使其在需要時可以接收更多的參數。這可以讓程式維護者可以視需要增加欄位,但不需更新整個巨集的定義。
  4. 使用名稱DO作為列表巨集中引數巨集的名稱。
#define FOR_LIST_OF_VARIABLES(DO) \
    DO(id1, name1) \
    DO(id2, name2) \
    DO(id3, name3)

同上,依此表可以產生以下的變數宣告:

#define DEFINE_NAME_VAR(id, name, ...) int name;
FOR_LIST_OF_VARIABLES( DEFINE_NAME_VAR )

或是宣告enumeration:

#define DEFINE_ENUMERATION(id, name, ...) name = id,
enum IdListType
{
    FOR_LIST_OF_VARIABLES( DEFINE_ENUMERATION )
};

用類似方式,也可以產生用printf顯示變數和名稱的程式。

void print_variables(void)
{
    #define PRINT_NAME_AND_VALUE(id, name, ...) printf(#name " = %d\n", name);
    FOR_LIST_OF_VARIABLES( PRINT_NAME_AND_VALUE )
}

相關條目

參考資料

Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads