C 在##连接之前计算预处理器令牌
我希望在将令牌与其他对象连接之前对其求值。“问题”在于标准规定了以下行为: 在重新检查替换列表以获取更多宏名称之前 替换,替换中的##预处理令牌的每个实例 列表(不是从参数中)被删除,并且前面的预处理 令牌与以下预处理令牌连接 因此,在下面的示例中C 在##连接之前计算预处理器令牌,c,c-preprocessor,string-concatenation,stringification,C,C Preprocessor,String Concatenation,Stringification,我希望在将令牌与其他对象连接之前对其求值。“问题”在于标准规定了以下行为: 在重新检查替换列表以获取更多宏名称之前 替换,替换中的##预处理令牌的每个实例 列表(不是从参数中)被删除,并且前面的预处理 令牌与以下预处理令牌连接 因此,在下面的示例中 #include <stdlib.h> struct xy { int x; int y; }; struct something { char * s; void *ptr; int size
#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 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
,并让宏使用该前缀?您可以为此使用二级扩展,例如
#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)
像
这样就行了
#define A One
#define B Two
CONCAT(A, B) // Results in: OneTwo
是的,我喜欢这个。不需要更改旧的宏,也不需要为其他宏创建可能的合并问题,而且即使双扩展可能无法直观地理解,但很明显,两个位置都使用相同的前缀。可能的重复请尽量减少示例:-)我从未理解为什么这样的事情需要两个级别。是宏扩展的第一级,是实际连接的第二级?这是因为
\define
指令中的连接运算符#
和字符串化运算符
禁止宏扩展。
#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