编写一个使用传递的参数名称的可变参数宏

时间:2014-01-07 08:56:40

标签: c macros variadic-functions variadic-macros

我想写一个变量宏,它以某种方式知道传递的参数的名称。 例如:

代码:

int x = 2;
float f = 4.6;
char c = 'A';
char* str = "Bla bla";
PRINT("%d  %f %c  %s", x, f, c, str);     // calling the macro

应产生输出

x=2 f=4.6 c=A str=Bla bla.

希望有人知道答案。

6 个答案:

答案 0 :(得分:5)

关闭但不完全(仅适用于单一表达)提问者需要的内容:

#define PRINT(fmt, var) printf(#var " = " fmt, (var))

以下是一个例子:

#include <stdio.h>
#include <stdlib.h>

#define PRINT(fmt, var) printf(#var " = " fmt, (var))

int
main(int argc, char *argv[])
{
    int x = 2, y = 3;
    float f = 4.6;
    char c = 'A';
    char *str = "Bla bla";
    PRINT("%d\n", x);
    PRINT("%f\n", f);
    PRINT("%c\n", c);
    PRINT("%s\n", str);
    PRINT("%d\n", x+y);
    exit(EXIT_SUCCESS);
}

答案 1 :(得分:1)

仔细阅读 cpp的文档。特别是关于macro argumentsstringificationconcatenationvariadic macros。这里有很好的解释。

您可能无法完全达到您想要的效果,因为您需要拆分格式字符串。

可能会降低您的目标(例如,仅接受PRINT一个参数,请参阅thisthat个答案)或考虑使用更强大的预处理器,例如{ {3}}

您也可以自定义GCC(通过添加您的内置)与例如GPP但这可能不值得这几周的努力(对于新手)。

答案 2 :(得分:1)

我认为你无法达到你想要的效果。

但是这样的事情可能是你的:

#define PRINT(fmt, val) fprintf(stderr, "%s=" fmt, #val, val)

...

int x = 2;
float f = 4.6;
char c = 'A';
char* str = "Bla bla";
// calling the macro:
PRINT("%d  ", x);
PRINT("%f ", f);
PRINT("%c  ", c);
PRINT("%s\n", str);

答案 3 :(得分:1)

你可能想要的东西:

#include <stdio.h>

#define STRINGIFY(x) #x, (x)
#define FPRINTF(file, fmt, ...) fprintf(file, fmt, __VA_ARGS__)
#define PRINTF(fmt, ...) FPRINTF(stdout, fmt, __VA_ARGS__)

int main(void)
{
  int i = 42;
  char ch = 'a';
  char str[4] = "alk";

  PRINTF("%s=%s, %s=%c, %s=%d\n", 
    STRINGIFY(str), 
    STRINGIFY(ch), 
    STRINGIFY(i)
  );

  /* of just use printf directly: */
  printf("%s=%s, %s=%c, %s=%d\n", 
    STRINGIFY(str), 
    STRINGIFY(ch), 
    STRINGIFY(i)
  );

  return 0;
}

答案 4 :(得分:1)

/投入印第安纳琼斯的帽子/

我可能有点太晚了,但我在这里说这个问题确实有一个合适的( - )解决方案。

首先,一些先决条件定义(explanation here):

#define L(c, ...) \
L4(c,1,0,,,,,,,,,,,,,##__VA_ARGS__) L4(c,0,1,,,,,,,,,##__VA_ARGS__) \
L4(c,0,2,,,,,        ##__VA_ARGS__) L4(c,0,3,        ##__VA_ARGS__)

#define L4(c, f, n, ...) \
L3(c,f,n##0,,,,__VA_ARGS__) L3(c,0,n##1,,,__VA_ARGS__) \
L3(c,0,n##2,,  __VA_ARGS__) L3(c,0,n##3,  __VA_ARGS__)

#define L3(...) L2(__VA_ARGS__, \
1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,  0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, )

#define L2(c, f, \
n00,n01,n02,n03, n04,n05,n06,n07, n08,n09,n0A,n0B, n0C,n0D,n0E,n0F, \
a00,a01,a02,a03, a04,a05,a06,a07, a08,a09,a0A,a0B, a0C,a0D,a0E,a0F, \
s, ...) L##s(c, f, n00, a00)

#define L1(c, f, n, a) c##f(n, a)
#define L0(c, f, n, a)

那么代码,实际上是@alk的答案的扩展名:

#include <stdio.h>

#define STRING1(n, a) #a, (a)
#define STRING0(n, a) , STRING1(n, a)
#define PRINTF(fmt, ...) printf(fmt, L(STRING, __VA_ARGS__))

int main(int argc, char *argv[]) {
    int i = 42;
    char ch = 'a';
    char str[4] = "alk";
    /** every var must be preceded with '%s' for its name to be shown **/
    PRINTF("%s=%s, %s=%c, %s=%d\n", str, ch, i);
    return 0;
}

此版本仅适用于[0..16]参数,但它可以很容易地扩展到任何参数计数,尤其是2的幂。但是,它支持的参数越多,它看起来就越不优雅。

P.S。:@BasileStarynkevitch已经提供了所有正确的链接,以阐明其工作原理。

答案 5 :(得分:-1)

接下来的工作对我来说是gcc 4.7:

#include <stdio.h>
#define PRINT(...) fprintf (stderr, __VA_ARGS__)

int main()
{
int x = 2;
float f = 4.6;
char c = 'A';
char* str = "Bla bla";
PRINT("%d  %f %c  %s", x, f, c, str); // calling the macro
}

(请注意我编辑了宏调用,更改了%s的%s)

此致