如何避免使用有条件编译的NSLog替换的“未使用的变量”编译器警告?

时间:2010-09-13 14:56:28

标签: cocoa cocoa-touch compiler-warnings nslog conditional-compilation

这源于我搜索NSLog()的智能变体。 BetterLog()的一个关键特性是NSLog()替换为发布和分发版本编译为空。建议的解决方案(参见例如Is it true that one should not use NSLog() on production code?)定义一个预处理器符号来控制BetterLog()的定义,具体取决于构建的类型。典型地:

#ifdef DEBUG_MODE
    #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
    #define DebugLog( s, ... ) 
#endif

其中DEBUG_MODE将被定义为仅用于调试版本的预处理器符号。

但是,在许多情况下,即当使用中间变量构建日志记录语句时,结果是未使用变量的编译器警告。这是一个例子:

if (error) {
    NSString *titleString = @"Error downloading thumbnail, will rebuild it";
    NSString *messageString = [error localizedDescription];
    NSString *moreString = [error localizedFailureReason] ? [error localizedFailureReason] : NSLocalizedString(@"Check the URL.", nil);
    BetterLog(@"%@: %@. %@", titleString, messageString, moreString);
} // silently ignoring *this* error is OK.

这里所有三个字符串都会产生编译器警告。而且我讨厌编译器警告。

当然,如果不以某种方式有条件地包括变量声明本身,就无法避免。我做了以下尝试,但它不起作用:

而不是仅仅在调试模式下定义DEBUG_MODE,我一直定义它,在调试模式下值为1,在发布模式下值为0。

然后我尝试利用编译器死代码剥离优化:

if (DEBUG_MODE && error) {
    // snip
}

代码正常:它在发布模式下被正确删除。然而,编译器仍会发出未使用的变量警告。

所以问题是:是否有可能做得比丑陋更好:

#if DEBUG_MODE
if (error) {
    // snip
}
#endif

1 个答案:

答案 0 :(得分:1)

一种选择是:

#define BetterLog(...) do { (void)(__VA_ARGS__); } while (0)

这样做的好处是,如果你到达BetterLog(),它的参数的任何副作用都将被评估,并且它是一个干净的语句所以它不是写if (x) BetterLog(@"%@", x);的错误(这将破坏下一个语句使用你的宏。)

就个人而言,我更喜欢使用“丑陋”的预处理器方法,因为它明确地排除了调试代码。