X巨集

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

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

X巨集的使用可以追溯到1960年代Meyers, Randy. The New C: X Macros. Dr.Dobb's 2001.，在現今的C语言和C++語言中仍可使用，但和其他語言特性相比較，知道X巨集的人比較少Bright, Walter. The X Macro. Digital Mars 2010Lucas, Andrew. Reduce C-language coding errors with X macros. Embedded.com 2013。
實現
X巨集包括兩部份：

 列表元素的定義
 列表的展開，產生部份的宣告或是敘述

列表是由巨集或是標頭檔所定義（命名為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);
}
範例2，用X巨集為參數
此範例設法提高X巨集的可讀性：

 定義列表的巨集名稱前面加上FOR_。
 將工作巨集以參數方式傳遞給列表巨集。一方面可以避免定義一個名稱無法表示用途的巨集X，也避免後續需要undefine該巨集。
 使用可变参数宏...的語法在工作巨集中，使其在需要時可以接收更多的參數。這可以讓程式維護者可以視需要增加欄位，但不需更新整個巨集的定義。
 使用名稱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 )
}

相關條目
可变参数宏
參考資料

Category:C語言