2012-09-30 43 views
3

你將如何編寫一個可以帶1或0參數的可變參數宏。即像這樣:需要0或1個參數的變量宏?

GREET()   // returns @"Hello World" 
GREET(@"John") // returns @"Hello John" 
+1

這是Objective-C的,那麼,由於您使用「@」字符串「成語」,對吧? –

+0

@ RichardJ.RossIII yeah – lms

回答

9

這是很簡單的,你有這樣的事情:

#define __NARGS(unused, _1, _2, _3, _4, _5, VAL, ...) VAL 
#define NARGS(...) __NARGS(unused, ## __VA_ARGS__, 5, 4, 3, 2, 1, 0) 

#define __GREET(ARGC, ARGS...) GREET_ ## ARGC (ARGS) 
#define _GREET(ARGC, ARGS...) __GREET(ARGC, ARGS) 
#define GREET(...) _GREET(NARGS(__VA_ARGS__), __VA_ARGS__) 

#define GREET_0(...) @"Hello World!" 
#define GREET_1(ARG, ...) @"Hello, " ARG // strings are auto-concatenated in objc 

int main() 
{ 
    NSLog(@"%@", GREET()); 
    NSLog(@"%@", GREET(@"John")); 
} 

輸出:

 
2012-09-30 11:56:48.478 TestProj[51823:303] Hello World! 
2012-09-30 11:56:48.480 TestProj[51823:303] Hello, John 

現在,這是相當複雜的,但假設你在一個基本水平明白是怎麼預處理器作品,你應該很好地理解發生的事情。

+3

太棒了。 「很簡單」,但? ;) –

+0

@JimBuck當你將它與我所做的其他一些東西(一個'switch'語句支持objc對象,對象範圍的局部變量,在C中編寫一個完整的應用程序,以上帝的名義)比較時,這實際上非常簡單。 –

+0

我對目標C不太熟悉,但在C中,您的宏將使用gcc擴展名「eat-the-comma」。這不能移植到標準C.(還有另一種符合標準的方法來檢查空的宏參數,它涉及更多一點。) –

1

一個宏有可變參數,或者它有固定數量的參數。要獲得所需的結果,請聲明2個宏,一個帶有0個參數,另一個帶有1個參數。

2

一個好辦法做到這一點是建立一個數據結構重複元素,如:

union greet_arg { 
    char *string; 
}; 
struct greet_args { 
    union greet_arg *arg[2]; 
}; 
void greet_function(struct greet_args *x); 

您的宏然後可以像這樣實現的:

#define GREET(x...) greet_function(&(struct greet_args){0, x}) 

現在的原因這項工作是,如果你打電話GREET("foo")那麼你會得到:

greet_function(&(struct greet_args){0, "foo"}); 

而如果你c所有GREET()你:

greet_function(&(struct greet_args){0, }); 

這是仍然有效; 「0」只是空值 - 填充數組的其餘部分。

您的greet_function()然後只需檢查x->arg[1]

+1

有趣,但請注意,由於您創建了C99複合字面值,這確實會導致創建本地範圍的iVar的(最小)開銷。 –

+0

@ RichardJ.RossIII - 在'gcc -O2'下,它實際上產生與您的示例完全相同的程序集,並且具有實際使用非文字參數的優點。 – geocar

+0

你必須記住,大多數objc用戶不會使用GCC,而是使用clang。我強烈要求你在那裏重新測試。 –

4

我不知道這是否會爲Objective C的工作,但對於C99和C11可以使用P99具有宏觀元P99_IF_EMPTY

#define GREET(...) P99_IF_EMPTY(__VA_ARGS__)("Hello World")("Hello " __VA_ARGS__) 
+0

考慮到objc使用與C完全相同的預處理器的事實,我不明白爲什麼這不起作用。 +1。 –

相關問題