我如何合并两个宏初始化字符串数组在C?

btxsgosb  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(93)

我正在使用C中的两个宏,并希望将它们合并来初始化字符串数组。下面是有问题的宏:

#define FOREACH_T(ACTION) \
ACTION("T1", 1) \
ACTION("T2", 2) \
ACTION("T3", 3) 

#define FOREACH_K(ACTION) \
ACTION("K1", 17) \
ACTION("K2", 20) \
ACTION("K3", 23)

字符串
我的目标是合并以这样的方式组合这些宏,以获得一个值数组,例如,索引[1 + 17]处的元素是"T1_K1"
对于如何将这些宏合并组合起来以达到预期的结果,我有点不知所措。我想得到这样的东西:

const char* value[] = { [1 + 17] = "T1_K1", [1 + 20] = "T1_K2", [1 + 23] = "T1_K3",
                        [2 + 17] = "T2_K1", [2 + 20] = "T2_K2", [2 + 23] = "T2_K3",
                        [3 + 17] = "T3_K1", [3 + 20] = "T3_K2", [3 + 23] = "T3_K3"};
};

apeeds0o

apeeds0o1#

如果你能改变列表宏,那么这很简单。不改变宏也是可能的,但是更难。

#define FOREACH_T(ACTION, ...) \
    ACTION("T1", 1, __VA_ARGS__) \
    ACTION("T2", 2, __VA_ARGS__) \
    ACTION("T3", 3, __VA_ARGS__) 

#define FOREACH_K(ACTION, ...) \
    ACTION("K1", 17, __VA_ARGS__) \
    ACTION("K2", 18, __VA_ARGS__) \
    ACTION("K3", 19, __VA_ARGS__) 

#define FOO(s, x, s2, x2) [x + x2] = s "_" s2,
#define FOO2(s, x, ...) FOREACH_T(FOO, s, x)

const char* value[] = {
    FOREACH_K(FOO2,)
};

字符串
请注意,这会发出warning: initializer overrides prior initialization of this subobject,因为例如1+18 == 2+17等等。
在不改变宏的情况下也是一样的,它使用macro_sequence_for,这是我为编写预处理器循环而创建的一个库,否则会太麻烦。
请注意,这样,你也可以将宏简化为像("T1",1)("T2",2)("T3",3)这样的列表,而不需要接受另一个宏作为参数。
在gcc.godbolt.org上运行

#include <macro_sequence_for.h>

#define FOREACH_T(ACTION) \
    ACTION("T1", 1) \
    ACTION("T2", 2) \
    ACTION("T3", 3)

#define FOREACH_K(ACTION) \
    ACTION("K1", 17) \
    ACTION("K2", 18) \
    ACTION("K3", 19)

#define IDENTITY(...) __VA_ARGS__
#define PARENS(...) (__VA_ARGS__)

#define BODY(n, d, name, value) BODY2(IDENTITY d, name, value)
#define BODY2(...) BODY3(__VA_ARGS__)
#define BODY3(name1, value1, name2, value2) [value1 + value2] = name1 "_" name2,

#define OUTER_BODY(n, d, name, value) SF_FOR_EACH0(BODY, SF_STATE, SF_NULL, (name, value), FOREACH_K(PARENS))

const char *value[] = {
    SF_FOR_EACH(OUTER_BODY, SF_NULL, SF_NULL,, FOREACH_T(PARENS))
};

相关问题