【问题标题】:"too many arguments for format" with macro带有宏的“格式参数太多”
【发布时间】:2020-09-04 16:00:18
【问题描述】:

我有一个调试宏,用于快速和脏输出。我一直在尝试确定如何在 gcc 5.4 上使代码编译干净。它对早期版本的 gcc (4.x) 或 clang (11.0.3) 没有任何问题。错误是这样的:

main.c: In function ‘main’:
main.c:4:38: warning: too many arguments for format [-Wformat-extra-args]
         do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                                      ^
main.c:10:2: note: in expansion of macro ‘DEBUGPRINT’
  DEBUGPRINT("How to have no arguments?\n", NULL);

我用来确定如何解决此问题的代码是:

#include <stdio.h>

#define DEBUGPRINT(fmt, ...) \
    do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                            __LINE__, __func__, __VA_ARGS__);} } while (0)

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n", NULL);
    return(0);
}   

正如大家所见,如果我有论据,没有问题。只有当我有一条没有参数的消息时。我想我可以通过“%s”传递一个“\n”,但我只是好奇是否有办法处理 NULL。

【问题讨论】:

  • if (1) { … } 在您的宏定义中的作用是什么?
  • @KonradRudolph 当我删除代码以制作更简单的版本时,这是一个遗留项目。这是因为构建中有不同的调试结构,所以这通常是一个定义。

标签: c macros


【解决方案1】:

fmt 参数需要省略,您需要将打印的固定部分与传入的参数分开。

#include <stdio.h>

#define DEBUGPRINT(...) \
    do { printf("debug:%s:%04d:%s: ", __FILE__, __LINE__, __func__);\
         printf(__VA_ARGS__);\
    } while (0)

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n");
    return(0);
}

输出:

debug:x1.c:0016:main: nums: 4660, 22136
debug:x1.c:0017:main: How to have no arguments?

【讨论】:

  • 按照OP的方式粘贴两个字符串字面量是完全有效的;你的代码没有做 OP 想要的。警告看起来很虚假。
  • @KonradRudolph 我忘了从参数列表中删除fmt。固定。
  • 呃,没关系,我误读了 GCC 的警告。当然 GCC 是对的。但是您的答案仍然没有达到 OP 的想法。
  • @KonradRudolph 如果没有传递格式参数,则会出现语法错误,因为__VA_ARGS__ 将为空。这解决了这个问题。
  • DEBUGPRINT("How to have no arguments yet with a %?\n") 将是一个问题,因为__VA_ARGS__ 需要是一个有效的格式字符串。
【解决方案2】:

为了没有参数,您可以执行以下操作:

#include <stdio.h>

/* SEPARATE THE COMMA FROM THE __VA_ARGS__ macro with
 * the ## token */
#define DEBUGPRINT(fmt, ...) \
    do { if (1){ fprintf(stdout, "debug:%s:%04d:%s: " fmt, __FILE__, \
                            __LINE__, __func__,## __VA_ARGS__);} } while (0)
/* THIS TOKEN ELIMINATES THE COMMA ------------^^  */

int main(int argc, char *argv[])
{
    DEBUGPRINT("nums: %04i, %04i\n", 0x1234,0x5678);
    DEBUGPRINT("How to have no arguments?\n");
    return(0);
}   

我担心它没有包含在标准中,但它是 CLANG 和 GCC 编译器共享的扩展。

这是我系统上的输出:

$ a.out
debug:pru3225.c:0012:main: nums: 4660, 22136
debug:pru3225.c:0013:main: How to have no arguments?
$ _

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多