【问题标题】:Is it possible to get macro passed as optional argument to variadic function using va_arg是否可以使用 va_arg 将宏作为可选参数传递给可变参数函数
【发布时间】:2020-04-22 16:09:57
【问题描述】:

我有以下程序。它将宏作为可选参数传递给可变参数函数。在该函数定义中,我们是否能够在不扩展的情况下获得该宏。我已将类型用作 'char *' 并显示宏扩展字符串。任何获得宏的方法。

#include <stdio.h>
#include <stdarg.h>

#define CONN_DISALLOW 3201008
#define SYSLOG_CONN_DISALLOW  \
    "%d: Disallowing new connections. Reason: %s.\n", CONN_DISALLOW

void cp_syslog(int syslogid, ...);

void cp_syslog(int syslogid, ...)
{
        char *syslog_disallow;
        va_list ap;
        va_start(ap, syslogid);

        syslog_disallow = va_arg(ap, char *);

        printf("String is %s", syslog_disallow);
        printf("Macro is %s", SYSLOG_CONN_DISALLOW);

        va_end(ap);
}

int main()
{
        int id = 2;
        cp_syslog(id, SYSLOG_CONN_DISALLOW);
        return 0;
}

现在得到的输出为:

String is %d: Disallowing new connections. Reason: %s.
Macro is %d: Disallowing new connections. Reason: %s.

预期为:

String is SYSLOG_CONN_DISALLOW

我的期望是,如果不同的宏作为可选参数传递给同一个可变参数函数,如何处理特定的宏。

如下:

cp_syslog(id, SYSLOG_CONN_DISALLOW);
cp_syslog(id, SYSLOG_CONN_ALLOW);
cp_syslog(id, SYSLOG_ICMP_DISALLOW);

【问题讨论】:

  • 嗯。宏得到扩展,这就是它们的用途。预处理后,宏名称从源代码中消失。您可以将宏的名称传递为"SYSLOG_CONN_DISALLOW" 以获得您想要的,但它看起来不像您真正想要的。显然您正试图拥有一个错误代码和相关消息系统。
  • @M Oehm 和@bruno:我明白你使用"SYSLOG_CONN_DISALLOW" 的意义。但是我不允许像上面那样发送宏。因为有将近 400-500 个不同的宏作为 arg 传递给cp_syslog()。通过这种编程,任何可能都可以提取宏名称。
  • 函数cp_syslog 是否总是像您的示例中那样调用:syslog(id, macro)?如果是这样,则不需要可变参数,但可以将 cp_syslog 包装在字符串化宏中。
  • @renga_in_stack 我编辑了我的答案
  • @bruno :感谢您提供帮助并确认宏中的一些内容。

标签: c c-preprocessor variadic-functions variadic-macros


【解决方案1】:

第一种可能性是做

cp_syslog(id, "SYSLOG_CONN_DISALLOW");

执行:

pi@raspberrypi:/tmp $ ./a.out
String is SYSLOG_CONN_DISALLOWMacro is %d: Disallowing new connections. Reason: %s.
pi@raspberrypi:/tmp $ 

(在第一个printf 中缺少换行符或执行cp_syslog(id, "SYSLOG_CONN_DISALLOW\n")

但这是人为的,甚至cp_syslog 的定义也是人为的,因为人们知道宏是SYSLOG_CONN_DISALLOW 在其定义中。


如果你想给“其他东西”一个宏的名称和它的“值”,只需使用一个中间宏,比如:

#define NAME_VALUE(x) #x, x

NAME_VALUE(SYSLOG_CONN_DISALLOW)的扩展为"SYSLOG_CONN_DISALLOW", "%d: Disallowing new connections. Reason: %s.\n", 3201008

那时cp_syslog不必知道它适用于SYSLOG_CONN_DISALLOW

#include <stdio.h>
#include <stdarg.h>

#define CONN_DISALLOW 3201008
#define SYSLOG_CONN_DISALLOW  \
    "%d: Disallowing new connections. Reason: %s.\n", CONN_DISALLOW

#define NAME_VALUE(x) #x, x /* ADDED */

void cp_syslog(int syslogid, ...);

void cp_syslog(int syslogid, ...)
{
  char *syslog_disallow;
  va_list ap;
  va_start(ap, syslogid);

  syslog_disallow = va_arg(ap, char *);

  printf("String is %s\n", syslog_disallow); /* \n ADDED */
  printf("Macro is %s", va_arg(ap, char *)); /* MODIFIED */

  va_end(ap);
}

int main()
{
        int id = 2;
        cp_syslog(id, NAME_VALUE(SYSLOG_CONN_DISALLOW)); /* MODIFIED */
        return 0;
}

编译和执行:

pi@raspberrypi:/tmp $ gcc pp.c
pi@raspberrypi:/tmp $ ./a.out
String is SYSLOG_CONN_DISALLOW
Macro is %d: Disallowing new connections. Reason: %s.
pi@raspberrypi:/tmp $ 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 2014-10-20
    • 1970-01-01
    • 2015-09-22
    • 2018-03-26
    相关资源
    最近更新 更多