我有以下两个宏:
#define F1(...) [NSString stringWithFormat:__VA_ARGS__]
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
当我嵌套它们时,F1可以工作,但F2无法编译。
此代码:
F1(@"%@", F1(@"%@", @"a"));
F2(@"%@", F2(@"%@", @"a"));
导致以下clang错误:
foo.m:51:15: warning: implicit declaration of function 'F2' is invalid in C99 [-Wimplicit-function-declaration]
F2(@"%@", F2(@"%@", @"a"));
^
foo.m:18:64: note: expanded from macro 'F2'
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
^
foo.m:51:15: warning: format specifies type 'id' but the argument has type 'int' [-Wformat]
F2(@"%@", F2(@"%@", @"a"));
~~ ^~~~~~~~~~~~~~~
%d
foo.m:18:64: note: expanded from macro 'F2'
#define F2(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
请注意,F1没有警告或错误,只有F2有问题。
这里发生了什么:这是预期的行为还是clang中的错误?
更重要的是,有没有办法让我调整F2才能让它发挥作用。我更喜欢F2的语法。
更新
按照@KenThomases的建议,我跑了clang -E -o foo.i foo.m
# 1 "foo.m"
# 1 "<built-in>" 1
# 1 "<built-in>" 3
# 178 "<built-in>" 3
# 1 "<command line>" 1
# 1 "<built-in>" 2
# 1 "foo.m" 2
NSLog([NSString stringWithFormat:@"%@", [NSString stringWithFormat:@"%@", @"a"]]);
NSLog([NSString stringWithFormat:(@"%@"), F2(@"%@", @"a")]);
我将此作为缺陷提交给llvm.org:Bug 19141
答案 0 :(得分:1)
在我看来,预处理器并没有扩展F2
宏的内部使用。显然,使用##__VA_ARGS__
只是插入F2
逐字外部使用的参数,而不是进一步扩展。
您可以让编译器预处理代码,它会告诉您发生了什么。 cc -E -o foo.i foo.c