2016-10-28 102 views
0

我想寫一個宏來初始化複雜結構的字段。在這種結構中,某些成員是我想用有效地址初始化的指針,有時候是NULL。 結構可以如下簡化:爲什麼初始化爲靜態指針無效?

typedef struct { 
int * p; 
} MYSTRUCT; 

我在宏觀第一遍是:

#define INIT_STRUCT(x) {&(x)} 

和用法是:

static int foo; 
static MYSTRUCT struct1 = INIT_STRUCT(foo); 

這個效果很好,當我初始化到一個真正的指針,但以下不起作用:

static MYSTRUCT struct2 = INIT_STRUCT(NULL); 

,因爲它是作爲{&(NULL)}開發的,編譯器(有理)標記爲&作爲錯誤常量。 我知道我可以選擇將&作爲參數的一部分,而不是宏觀主體的一部分,但這在我的情況下並不方便,也不能接受編譯器的勝利,所以我試圖變得更聰明下面的第二個版本的宏:

static void * NOTHING; 
#define INIT_STRUCT(x) {&NOTHING == &(x) ? NULL : &(x)} 

與使用

MYSTRUCT struct1 = INIT_STRUCT(foo); 
MYSTRUCT struct2 = INIT_STRUCT(NOTHING); 

但是編譯器抗議「初始化不是一個常量」。 如果我用1 == 2代替&NOTHING == &(x),則沒有錯誤,所以條件的格式不是問題。 另一方面,&NOTHING&(foo)本身作爲初始值設定項是有效的。

編譯器在使我的「智能」宏無效時是否正確? 除了將&作爲foo參數的一部分外,還有其他解決方案嗎?

該編譯器是Microsoft Visual Studio C 2010 Ultimate。

+4

爲什麼不能簡單定義'INIT_STRUCT'宏如'的#define INIT_STRUCT(X){(X)}',並且使用它作爲'INIT_STRUCT(富) '?對於代碼讀者而言,它會對所發生的事情更加透明,當然可以通過使用NULL來解決您的問題。 –

+1

除了@Someprogrammerdude所說的,你還可以定義2個宏;一個用於普通情況,一個用於特殊情況。應該避免使用宏來實現「智能」,因爲宏不是非常靈活,並且可能在以後導致其他問題。 – user694733

回答

1

您可以簡化和使用它。

#define INIT_STRUCT(str, x) {str -> p = x} 

這用作

INIT_STRUCT(struct1, foo); 
INIT_STRUCT(struct2, NULL); 
+0

這是分配,而不是初始化。因此,它不適用於'const'變量。 – user694733