如何定义一个C宏,它将根据传递给该函数的变量值生成变量名称(标记)?在下面的示例中,查找MEMBER宏的有效版本。
e.g。给定下面的结构,我需要定义一个宏,它将根据传递给函数的变量值生成变量名。
struct foo {
uint32_t bar0_data;
uint32_t bar0_status;
uint32_t bar1_data;
uint32_t bar1_status;
...
};
#define MEMBER(x, n, f) x -> bar ## n ## _ ## f
void write_val(struct foo *foo, int which_bar)
{
MEMBER(foo, which_bar, data) = 1;
MEMBER(foo, which_bar, status) = 2;
}
这适用于在此主题上具有不同变体的巨型结构,因此定义具有成员结构数组的新结构不是一种选择。
答案 0 :(得分:1)
你必须考虑允许你执行"的语言。您即时生成的文本(如JavaScript
)。 C
的不同之处在于,从源文本到正在运行的二进制文件的转换在以下步骤中发生:
pre-processor
指令)运行#include
- 程序文本已修改的地方compiler
- 这会将步骤1的结果转换为机器代码(无论是通过使用Assembler
语言的中间步骤还是直接执行)在任何情况下运行时行为都会在<{1}}步骤之后发生 way ,因此pre-processor
无法找到您要查找的内容语言(缺少编写自我修改程序,重新编译并重新启动自己)
答案 1 :(得分:1)
C不允许您以这种方式创建动态名称。
您可以使用查找表来模拟它。
但是,您实际上只想从运行时数据中找到Output0Buffer.memberOf= result.Properties["memberOf"][0].ToString();
中的特定字段。这可以通过几种方式完成。例如,一个switch语句。
result.Properties["memberOf"]
如果您更愿意使用文字表格,则可以存储字段的偏移量。
foo
但是,通过定义表示“switch (which_bar) {
case 0: foo->bar0_data = 1;
foo->bar0_status = 1;
break;
...
}
”的结构,并在offset_t bar_data[] = {
offsetof(struct foo, bar0_data),
offsetof(struct foo, bar1_data),
...
};
offset_t bar_status[] = {
offsetof(struct foo, bar0_status),
...
};
#define BAR_DATA(FOO, WHICH) \
(*(uint32_t *)((char *)(FOO) + bar_data[WHICH]))
#define BAR_STATUS(FOO, WHICH) \
(*(uint32_t *)((char *)(FOO) + bar_status[WHICH]))
BAR_DATA(foo, which_bar) = 1;
BAR_STATUS(foo, which_bar) = 1;
中定义它们的数组,似乎可以更好地服务。
bar
答案 2 :(得分:0)
FWIW,想出了实现这个宏的一种方法,假设每个实例都出现在一个固定的偏移处:
#define DELTA(m1, m2) (offsetof(foo_t, m2) - offsetof(foo_t, m1))
#define MEMBER(x, n, f) \
*(uint32_t *)(((uint8_t *)& x -> bar0_ ## f) + \
(DELTA(bar0_ ## f, bar1_ ## f) * n))
它不会像最初请求的那样生成变量名称标记,但可以用来访问不必生成名称的值。