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

发布于 2024-09-18 12:50:44 字数 1558 浏览 7 评论 0原文

这是我对 NSLog() 的智能变体的搜索。 BetterLog() 的一个关键特性是,NSLog() 替代品在发布和分发版本中编译为空。建议的解决方案(参见例如 是确实,不应在生产代码上使用 NSLog()?)是定义一个预处理器符号来根据构建类型控制 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

This comes out of my search for a smart variant of NSLog(). One key feature of BetterLog() is that the NSLog() replacement compiles out to nothing for release and distribution builds. The proposed solution (see eg Is it true that one should not use NSLog() on production code?) is define a preprocessor symbol to control the definition of BetterLog() depending on the kind of build. Typically:

#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

where DEBUG_MODE would be defined as a preprocessor symbol only for debug builds.

However, in a number of cases, namely when the logging statement was built with intermediary variables, the result is a compiler warning for unused variables. Here is an example:

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.

Here all three strings yield compiler warnings. And I hate compiler warnings.

Of course it's impossible to avoid without somehow conditionally including the variables declarations themselves. I made the following attempt, but it didn't work:

instead of simply defining DEBUG_MODE in debug mode only, I define it all the time, with value 1 in debug mode, and value 0 in release mode.

Then I tried to take advantage of the compiler dead code stripping optimization :

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

The code is OK: it is correctly stripped out in release mode. Yet the compiler still emits the unused variable warnings.

So the question is: isn't it possible to do any better than the ugly:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

心如狂蝶 2024-09-25 12:50:44

一种选择是:

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

这样做的优点是,如果您到达 BetterLog(),将评估其参数的任何副作用,并且这是一个干净的语句,因此编写 if (x) BetterLog(@ "%@", x); (这会破坏使用宏的下一条语句)。

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

One option would be:

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

This has the advantage that if you reach a BetterLog(), any side effects of its arguments will be evaluated, and it’s a clean statement so it’s not a bug to write if (x) BetterLog(@"%@", x); (which would break the next statement using your macro).

Personally, I prefer to use the “ugly” preprocessor approach, because it’s explicit about excluding the debug code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文