【问题标题】:C Macro Stringify Only If Argument is Present仅当存在参数时才进行 C 宏字符串化
【发布时间】:2021-10-03 14:32:40
【问题描述】:

我试图弄清楚如何编写一个预处理器宏,该宏只有在存在参数时才会“字符串化”其参数

例如:

STRINGIFY(foo) -> "foo"
STRINGIFY() ->

在我非常基本的例子中:

#define STRINGIFY(x) #x

调用 STRINGIFY() 的结果是 "" 而不是什么都没有(这是我想要的)

如何做到这一点?

编辑

作为我为什么想要这种行为的一个例子,我正在使用宏来为这样的字符串数组生成一个初始化器

const char* STRINGS[] = {MAP_LIST(STRINGIFY, __VA_ARGS__)}; 

其中 MAP_LIST 来自以下项目:https://github.com/swansontec/map-macro

如果我的 VA_ARGS 里面有项目,您最终会得到例如以下内容:

const char* STRINGS[] = {"a", "b", "c"}; 

但如果 VA_ARGS 为空,我会得到:

const char* STRINGS[] = {""};

因为,当你“字符串化”一个空参数时,它会给你一个空字符串。

【问题讨论】:

  • 在非字符串的情况下你会如何使用它?
  • 为什么不带参数调用它?
  • 这似乎更像是MAP_LIST() 的问题。它不能正确处理空列表,它会调用该函数一次。
  • 嗯... 0 大小的数组是非法的。您基本上是在努力获得无效的声明。
  • @0___________,每个版本的 C 语言规范都不允许零长度数组。一些实现(特别是 GCC)接受它们作为扩展。

标签: c c-preprocessor


【解决方案1】:

如何编写一个预处理器宏,只有当参数存在时才会“字符串化”它的参数

您可以做一个可变参数宏并放置一个带有() 的宏,该宏将扩展为一个逗号(或特定数量的逗号)并将__VA_ARGS__ 放在该宏和() 之间,然后重载参数数量.

#define TRIGGER_PARENTHESIS(...)  ,
#define STRINGIFY_0()
#define STRINGIFY_1(a)  #a
#define STRINGIFY_N2(_0,_1,N,...) STRINGIFY_##N
#define STRINGIFY_N(...) STRINGIFY_N2(__VA_ARGS__)
#define STRINGIFY(...) STRINGIFY_N(TRIGGER_PARENTHESIS __VA_ARGS__ (),0,1)(__VA_ARGS__)

请参阅A way to count the number of __VA_ARGS__ arguments, including 0, without compiler specific constructs 了解更稳健的方法。

使用带有 __VA_OPT__ 的编译器和较新的 C++,它只是:

#define STRINGIFY(...) __VA_OPT__(#__VA_ARGS__)

如 cmets 中所述,您的用例无效。如果MAP_LIST(STRINGIFY, __VA_ARGS__) 的结果为空,则结果为:

const char* STRINGS[] = {}; 

这是无效的 C 代码,因为 Is an empty initializer list valid C code?What happens if I define a 0-size array in C/C++? 。零大小的数组和空的初始化列表都是 GNU C 编译器的扩展。

【讨论】:

    猜你喜欢
    • 2012-08-11
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 2021-12-26
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    相关资源
    最近更新 更多