使用C预处理器创建多个表格布局

使用C预处理器创建多个表格布局,c,gcc,preprocessor,C,Gcc,Preprocessor,我需要根据一组通用的定义布局多个表(和结构)。为了保持所有内容的一致性,我希望将所有定义放在一个地方,并使用C宏的魔力将定义扩展到各种表(和结构)中 有一个问题:并非所有的桌子都是相同的长度。问题的简化说明如下所示: // Here is the master list of things #define THING_DEFINITIONS \ THING(apple, true) \ THING(pear, true) \ THING(caddilac, false) \ TH

我需要根据一组通用的定义布局多个表(和结构)。为了保持所有内容的一致性,我希望将所有定义放在一个地方,并使用C宏的魔力将定义扩展到各种表(和结构)中

有一个问题:并非所有的桌子都是相同的长度。问题的简化说明如下所示:

// Here is the master list of things
#define THING_DEFINITIONS \
  THING(apple, true) \
  THING(pear, true) \
  THING(caddilac, false) \
  THING(mango, true)

// I want a table of all thing names -- this works fine
#undef THING
#define THING(name, is_fruit) #name,
char *all_things[] = {
  THING_DEFINITIONS
};

// Now I want a table of just fruits -- the following does not work
#undef THING
#define THING(name, is_fruit) \
#if is_fruit \
 #name,      \
#endif

char *just_fruits[] = {
  THING_DEFINITIONS
};
当然,问题是条件不能出现在宏定义中,至少不能像这里显示的那样


东西
是否有一个定义,当我展开
东西_定义
时,它只会发出果实?

根据
是_果实
生成新的宏名称:

// Options
#define THING_true(name) #name,
#define THING_false(name)

// Combine symbols
#define CONCAT(a, b) a ## b

// Final macro
#define THING(name, is_fruit)  CONCAT(THING_, is_fruit) (name)
这将扩展到:

THING_true(apple)
THING_true(pear)
THING_false(caddilac)
THING_true(mango)
"apple",
"pear",

"mango",
最终将扩展到:

THING_true(apple)
THING_true(pear)
THING_false(caddilac)
THING_true(mango)
"apple",
"pear",

"mango",

我在Ideone上做了一个小测试:

侧注:为了保持名称空间干净,通常建议在使用后立即取消定义X宏(
THING
)?如果包含所有内容的列表必须完全按照显示的顺序排列,则比灵活排列更难。但你已经得到的建议触及了问题的核心。您需要不同的宏名称,以便根据上下文进行不同的扩展。(我可能会使用像
THING_FRUIT
这样的名称,而不是建议的名称,但名称是可延展的。)@JonathanLeffler:我喜欢user694733的解决方案,但你提到“这比顺序灵活更难”。现在我很好奇:技术是什么?哦,我想用
#定义事物#定义水果![2]东西
#定义水果![2]东西(苹果,真的)东西(梨,真的)东西(芒果,真的)
#定义松脆的东西(卡迪拉克,假的)
。如果我不想要脆脆的东西,我会有各种选择——直接引用水果类的东西,或者重新定义东西的定义,只引用水果类的东西。但是,在螺母和螺栓的层次上,这仍然是相同的基本想法(多个宏)-它只是对力学的一些小调整。如果数据中有更多的属性,可能会更有说服力。@JonathanLeffler啊-我明白你的意思。是的,我的用例更复杂:我必须保持外部索引与内部数据表中的插槽同步。外部索引是稀疏的,内部数据表是密集的。考虑到我这么快就想到了这一点,我担心我在生活中做了太多的宏滥用:-/没有太多的宏滥用:)!感谢IDENo.com网站(我知道GordBo.Org,但这是C++特定的)。