4

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

编码:

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.

希望有人知道这个问题的答案。

4

6 回答 6

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);
}
于 2014-01-07T09:12:25.740 回答
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);
于 2014-01-07T09:13:03.197 回答
1

仔细阅读cpp的文档。特别是关于宏参数字符串化连接可变参数宏。那里解释得很好。

您可能无法完全实现您想要的,因为您需要拆分格式字符串。

也许降低你的目标(例如只接受一个参数PRINT,看到这个那个答案)或考虑使用更强大的预处理器,如GPP

您也可以使用例如MELT自定义 GCC(通过添加您的内置程序),但这可能不值得为此付出数周的努力(对于新手而言)。

于 2014-01-07T09:01:40.837 回答
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;
}
于 2014-01-07T10:11:05.553 回答
1

/戴上印第安纳琼斯的帽子/

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

首先,一些先决条件定义(解释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 的幂。但是,它支持的参数越多,它看起来就越不优雅。

PS:@BasileStarynkevitch 已经提供了所有正确的链接来阐明它是如何工作的。

于 2016-10-18T13:55:02.953 回答
-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 更改为 %c 的宏调用)

问候

于 2014-01-07T09:08:08.197 回答