【问题标题】:Evaluate preprocessor token before ## concatenation在## 连接之前评估预处理器标记
【发布时间】:2023-03-09 10:46:01
【问题描述】:

我想先评估一个标记,然后再将它与其他东西连接起来。 “问题”是标准将行为指定为

在重新检查替换列表以获取更多宏名称之前 替换,替换中##预处理标记的每个实例 列表(不是来自参数)被删除并且前面的预处理 令牌与以下预处理令牌连接。

因此在下面的例子中,

#include <stdlib.h>

struct xy {
    int x;
    int y;
};

struct something {
    char * s;
    void *ptr;
    int size;
    struct xy *xys;
};
#define ARRAY_SIZE(a) ( sizeof(a) / sizeof((a)[0]) )

#define DECLARE_XY_BEGIN(prefix) \
struct xy prefix ## _xy_table[] = {

#define XY(x, y) {x, y},

#define DECLARE_XY_END(prefix) \
    {0, 0} \
}; \
struct something prefix ## _something = { \
    "", NULL, \
    ARRAY_SIZE(prefix ## _xy_table), \
    &(prefix ## _xy_table)[0],  \
};

DECLARE_XY_BEGIN(linear1)
    XY(0, 0)
    XY(1, 1)
    XY(2, 2)
    XY(3, 3)
DECLARE_XY_END(linear1)


#define DECLARE_XY_BEGIN_V2() \
struct xy MYPREFIX ## _xy_table[] = {

#define DECLARE_XY_END_V2() \
    {0, 0} \
}; \
struct something MYPREFIX ## _something = { \
    "", NULL, \
    ARRAY_SIZE(MYPREFIX ## _xy_table), \
    &(MYPREFIX ## _xy_table)[0],  \
};

#define MYPREFIX linear2
DECLARE_XY_BEGIN_V2()
    XY(0, 0)
    XY(2, 1)
    XY(4, 2)
    XY(6, 3)
DECLARE_XY_END_V2()
#undef MYPREFIX

最后一个声明扩展为

struct xy MYPREFIX_xy_table[] = {
 {0, 0},
 {2, 1},
 {4, 2},
 {6, 3},
{0, 0} }; struct something MYPREFIX_something = { "", 0, ( sizeof(MYPREFIX_xy_table) / sizeof((MYPREFIX_xy_table)[0]) ), &(MYPREFIX_xy_table)[0], };

而不是

struct xy linear2_xy_table[] = {
 {0, 0},
 {2, 1},
 {4, 2},
 {6, 3},
{0, 0} }; struct something linear2_something = { "", 0, ( sizeof(linear2_xy_table) / sizeof((linear2_xy_table)[0]) ), &(linear2_xy_table)[0], };

如我所愿。有什么方法可以定义产生这个的宏吗?第一组宏可以,但我想避免前缀重复,并且只定义一次。那么是否可以使用#define 设置前缀并让宏使用它?

【问题讨论】:

标签: c c-preprocessor string-concatenation stringification


【解决方案1】:

You can use a macro for concatenation点赞

#define CONCAT_(A, B) A ## B
#define CONCAT(A, B) CONCAT_(A, B)

这样就可以了

#define A One
#define B Two
CONCAT(A, B) // Results in: OneTwo

【讨论】:

  • 我一直不明白为什么这样的事情需要两个层次。一级是宏扩展,二级是实际串联?
  • 这是因为#define指令中的连接运算符##和字符串化运算符#抑制了宏扩展。
【解决方案2】:

您可以为此使用二级扩展,例如。

#define XY_HLP1(a) DECLARE_XY_BEGIN(a)
#define XY_HLP2(a) DECLARE_XY_END(a)
#define DECLARE_XY_BEGIN_V2() XY_HLP1(MYPREFIX)
#define DECLARE_XY_END_V2() XY_HLP2(MYPREFIX)

【讨论】:

  • 是的,我喜欢这个。无需更改旧的宏并为其他宏创建可能的合并问题,而且即使双扩展可能不直观地理解,仍然很明显两个地方使用了相同的前缀。
猜你喜欢
  • 1970-01-01
  • 2010-10-21
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 2017-06-01
  • 2016-05-08
  • 1970-01-01
  • 2018-11-22
相关资源
最近更新 更多