2017-04-12 69 views
9

我試圖應用X Macro概念,以便有可能將所有結構成員初始化爲自定義默認(無效)值。我寫了下面的代碼:爲什麼這個嵌套宏替換失敗?

#define LIST_OF_STRUCT_MEMBERS_foo \ 
    X(a) \ 
    X(b) \ 
    X(c) 

#define X(name) int name; 
struct foo { 
    LIST_OF_STRUCT_MEMBERS_foo 
}; 
#undef X 


#define X(name) -1, 
static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    LIST_OF_STRUCT_MEMBERS_foo 
    }; 
} 
#undef X 

#define X(name) -1, 
#define foo_DEFAULT_VALUE { LIST_OF_STRUCT_MEMBERS_foo } 
#undef X 

static struct foo test = foo_DEFAULT_VALUE; 

然而,當我運行預處理器的foo_DEFAULT_VALUE定義失敗-1,

預處理器的輸出來替代X(name)電話:

struct foo { 
    int a; int b; int c; 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    -1, -1, -1, /*Here the substitution worked nicely*/ 
    }; 
} 

static struct foo test = { X(a) X(b) X(c) }; /*Why this substitution failed?*/ 

我想C-macros could refer to other macros 。你知道替代失敗的原因嗎?有什麼解決方法嗎?

我可以和foo_invalidate住在一起,但我不願放棄直接在初始化時使用的值。

+2

你有''('name)'定義爲'-1,'''define''foo_DEFAULT_VALUE'',但不是你真正使用它的地方。你需要在'static struct foo test = foo_DEFAULT_VALUE'行的周圍定義'X'宏。 – Dmitri

回答

9

讓我們假設我們是預處理並且遇到該行:

static struct foo test = foo_DEFAULT_VALUE; 

通1:

static struct foo test = { LIST_OF_STRUCT_MEMBERS_foo }; 

通2:

​​

通過3:沒有擴大,因爲此線上未定義X


一個解決辦法可能是界定一個const變量(可能但不一定static)用作默認值:

#define X(name) -1, 
static const struct foo foo_DEFAULT_VALUE = { LIST_OF_STRUCT_MEMBERS_foo }; 
#undef X 

產生:

static const struct foo foo_DEFAULT_VALUE = { -1, -1, -1, }; 
+0

什麼可能是一種解決方法?我想過以下幾點,但我想知道它是否是最優的:'#define X(name)-1, #define foo_DEFAULT_VALUE_GENERATOR {LIST_OF_STRUCT_MEMBERS_foo} static const struct foo_DEFAULT_VALUE = foo_DEFAULT_VALUE_GENERATOR; #undef X' – Antonio

+0

那麼,直截了當的方式顯然是這樣。將聲明後面的'#undef'移動到行後面。否則需要重新設計。 –

+0

問題是X宏構造需要快速定義'X()'「......」 – Antonio

2

你可能會喜歡X_Macros的undef-free版本,
它減少了在每次使用時定義和取消定義所需的小心
並在多個代碼文件頭UND使用率更適合定義:

#define LIST_OF_STRUCT_MEMBERS_foo(mode) \ 
    X_##mode(a) \ 
    X_##mode(b) \ 
    X_##mode(c) 

#define X_struct(name) int name; 
#define X_list(name) -1, 
#define foo_DEFAULT_VALUE { LIST_OF_STRUCT_MEMBERS_foo(list) } 

struct foo { 
    LIST_OF_STRUCT_MEMBERS_foo(struct) 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    LIST_OF_STRUCT_MEMBERS_foo(list) 
    }; 
} 

static struct foo test = foo_DEFAULT_VALUE; 

輸出(GCC-E):

struct foo { 
    int a; int b; int c; 
}; 

static inline void foo_invalidate(struct foo* in) { 
    *in = (struct foo){ 
    -1, -1, -1, 
    }; 
} 

static struct foo test = { -1, -1, -1, }; 
+0

非常有趣的方法!你從哪裏知道的? – Antonio

+1

如果我說我發明了它,你會相信我嗎?我並不是說我首先發明瞭它(早些時候可能有其他的),但是我確實自己想出了它。 – Yunnosch

+0

我確實相信你,昨天我搜索了很多主題,從來沒有見過這樣的實現!只要有可能,我會盡快給你賞金! – Antonio

-1

您也可以嘗試檢查擴展宏的輸出。如果你使用gcc作爲編譯器,gcc -E <filename> >> full_src.txt'應該有所幫助。更多細節在這裏:Seeing expanded C macros

+0

這正是我填寫我的問題的'預處理器輸出:'部分 – Antonio