gcc 对无效语句的警告。

发布于 2024-11-27 02:52:38 字数 565 浏览 2 评论 0原文

我有一个日志记录宏,在发布模式下变为:

#define LOG (void)

So 语句

LOG("foobar %d", 0xbabecafe);

扩展为

(void)("foobar %d", 0xbabecafe);

问题是最后一个表达式在 gcc 下产生警告:

warning: left-hand operand of comma expression has no effect [-Wunused-value]

如何更改日志记录宏以便不发出警告? (请注意,我不想添加编译标志 -Wunused-value)。

编辑我已经看到几个涉及(...)的答案。相同的文件是在 Minix 下编译的,Minix 不支持可变参数宏。最好是有一个符合 C89 的解决方案。虽然你的答案是正确的(我赞成它),但我没有包含这个小细节是我的错。

I have a logging macro which in release mode becomes:

#define LOG (void)

So statement

LOG("foobar %d", 0xbabecafe);

is expanded to

(void)("foobar %d", 0xbabecafe);

The problem is that the last expression produces an warning under gcc:

warning: left-hand operand of comma expression has no effect [-Wunused-value]

How can I change the logging macro such that no warning is issued? (Note, that I don't want to add compiling flag -Wunused-value).

EDIT I see already a couple of answers involving (...). The same file is compiled under Minix which doesn't support variadic macros. The best would be to have a C89 conforming solution. While your answer is correct (and I upvoted it), it is my fault that I didn't include this small detail.

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

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

发布评论

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

评论(5

满地尘埃落定 2024-12-04 02:52:38

我认为处理这个问题的老派方法是利用双括号。像这样的东西:

LOG(("message: %d", 10));

然后对于你的宏,你可以这样定义它:

#define LOG(x) printf x

或者

#define LOG(x) (void)0

由于双括号,预处理器将整个内部括号视为单个参数。这至少曾经在视觉工作室中工作过。

编辑:我做了一个快速测试,它可以与带有-ansi的gcc一起使用,所以它应该很好:

gcc -DNDEBUG -ansi -pedantic -W -Wall test.c -o test< /代码>

#include <stdio.h>

#ifdef NDEBUG
#define LOG(x) printf x
#else
#define LOG(x) (void)0
#endif

int main() {
    LOG(("message: %d\n", 10));
    return 0;
}

I think the old school way of dealing with this is to take advantage of double parens. Something like this:

LOG(("message: %d", 10));

Then for your macro, you define it like this:

#define LOG(x) printf x

or

#define LOG(x) (void)0

Because of the double parens, the pre-processor treats the whole inner paren as a single parameter. This at least used to work in visual studio.

EDIT: I did a quick test, it works with gcc with -ansi, so it should be good:

gcc -DNDEBUG -ansi -pedantic -W -Wall test.c -o test

#include <stdio.h>

#ifdef NDEBUG
#define LOG(x) printf x
#else
#define LOG(x) (void)0
#endif

int main() {
    LOG(("message: %d\n", 10));
    return 0;
}
盗心人 2024-12-04 02:52:38

最简单的应该是

#define LOG(...) (void)0

(gcc 支持 C99 可变参数宏,并且现在大多数其他编译器也支持)这将丢弃参数列表,这有两个优点:

  • 它不会创建无效的语句,并且
  • 根本不会评估参数(如果您在参数列表中调用非内联函数,在您的版本中,编译器无法消除它们,而使用可变参数宏,编译器根本看不到它们。

The easiest should be

#define LOG(...) (void)0

(gcc supports the C99 variadic macros and most other compilers also do these days) That will discard the arguments list, which has two advantages:

  • it does not create statements with no effect and
  • the arguments are not evaluated at all (if you call non-inline functions in the argument list, in your version the compiler can't eliminate them, while with the variadic macro, the compiler won't see them at all.
獨角戲 2024-12-04 02:52:38

#define LOG(...) 似乎可以解决问题。

#define LOG(...) seems to do the trick.

明媚如初 2024-12-04 02:52:38

对于不合格的 C 实现(甚至不是 C89?)的问题,您可以做一些事情,

static void LOG(char *format, ...) { /* empty */ }

比如即使是完全愚蠢的编译器也应该能够优化它。

For your problems with a non-conforming C implementation (not even C89?) you could do something like

static void LOG(char *format, ...) { /* empty */ }

even a completely dumb compiler should be able to optimize that out.

神经大条 2024-12-04 02:52:38

我使用

#define LOG( t) t

过开发版本和

#define LOG( t)

发布版本,典型用途是

LOG( printf( "here\n"));

I've used

#define LOG( t) t

for the development version and

#define LOG( t)

for the release version, with a typical use being

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