1、問題

2、解決問題的辦法

將Build Setting下的Apple LLVM 7.0選擇成GUN99
3、產生此問題的原因
3.1、在NSException.h的文件中定義了如下宏
/* * Asserts to use in Objective-C method bodies */ #if !defined(NSAssert)//使用了NSAssert宏 #define NSAssert5(condition, desc, arg1, arg2, arg3, arg4, arg5) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), (arg1), (arg2), (arg3), (arg4), (arg5)) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #define NSAssert4(condition, desc, arg1, arg2, arg3, arg4) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), (arg1), (arg2), (arg3), (arg4), 0) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #define NSAssert3(condition, desc, arg1, arg2, arg3) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), (arg1), (arg2), (arg3), 0, 0) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #define NSAssert2(condition, desc, arg1, arg2) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), (arg1), (arg2), 0, 0, 0) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #define NSAssert1(condition, desc, arg1) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), (arg1), 0, 0, 0, 0) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #define NSAssert(condition, desc) \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ _NSAssertBody((condition), (desc), 0, 0, 0, 0, 0) \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS #endif
//在如下NSAssert的定義中,出現了##__VA_ARGS__ #define NSAssert(condition, desc, ...) \ do { \ __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \ if (!(condition)) { \ NSString *__assert_file__ = [NSString stringWithUTF8String:__FILE__]; \ __assert_file__ = __assert_file__ ? __assert_file__ : @"<Unknown File>"; \ [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd \ object:self file:__assert_file__ \ lineNumber:__LINE__ description:(desc), ##__VA_ARGS__]; \ } \ __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \ } while(0) #endif
3.2 ##__ VA_ARGS__的追本溯源
1)##__ VA_ARGS__代表帶有可變參數的宏
2)可變參數宏不被ANSI/ISO C++ 所正式支持。因此,你應當檢查你的編譯器,看它是否支持這項技術。
即Xcode的Build Setting下的Apple LLVM 7.0要選擇成GUN99。
3)在1999年版本的ISO C 標准中,宏可以象函數一樣,定義時可以帶有可變參數。宏的語法和函數的語法類似。下面有個例子:
//’…’指可變參數,被表示成零個或多個符號,包括里面的逗號. //當被調用時,在宏體(macro body)中,那些符號序列集合將代替里面的__VA_ARGS__標識符。 #define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)
4)GCC始終支持復雜的宏,它使用一種不同的語法從而可以使你可以給可變參數一個名字,如同其它參數一樣。例如下面的例子:
#define debug(format, args...) fprintf (stderr, format, args)
5)CPP使用一個特殊的’##’操作。書寫格式為:
//這里,如果可變參數被忽略或為空,’##’操作將使預處理器(preprocessor)去除掉它前面的那個逗號。 //如果你在宏調用時,確實提供了一些可變參數,GNU CPP也會工作正常,它會把這些可變參數放到逗號的后面。像其它的pasted macro參數一樣,注意這些參數不是宏的擴展。 #define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)
-
C/C++可變參數,“## __VA_ARGS__”宏的介紹和使用 » reille blog
— 今天閱讀代碼的時候,在一個宏定義語句中,發現了個之前未曾見過的編譯器預定義宏:“__VA_ARGS__”。當時,從代碼語句中推測它代表宏參數:“…”(本文稱之為省略號),依稀記得printf函數聲明中有使用這個省略號,大概的意思是表示可變化的參數,但未深入了解。