C 预处理器指针调配
C Preproccessor Pointer Swizzling
我试图避免静态 table 中的一个问题,即一个 table 引用另一个引用原始 table 的问题。编译器抱怨找不到 table 成员之一的定义。为了解决这个问题,我一直在模拟一些测试代码,这些方法是否可行?像我正在尝试做的事情有可能吗?
以下代码供参考:
#define SWIZTBLMAX 256
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };
typedef struct cli_term
{
char* name;
cli_term* parent;
cli_term* child;
}cli_termt;
typedef struct swiz_ent
{
cli_term* t;
char* n;
}swiz_ent;
static swiz_ent swizzle_tbl[SWIZTBLMAX];
static cli_term* swizzle(const char* n)
{
int i;
for(i=0;i<SWIZTBLMAX;i++)
{
if(strcmp(n,swizzle_tbl[i].n)==0)
return swizzle_tbl[i].t;
}
return NULL;
}
TERM( ct_show_test, "test", swizzle("ct_show"), NULL )
TERM( ct_quit, "quit", NULL, NULL )
TERM( ct_show, "show", NULL, swizzle("ct_show_test") )
所以,我的想法是将指针分配推迟到运行时,我在将对象写入磁盘和写入磁盘时做了类似的事情。有什么办法可以像这样创建静态 table 吗? (带有指向静态分配的其他结构的指针)
您可以通过在定义变量之前声明变量来在全局变量中进行循环引用:
struct foo {
struct foo *fooptr;
};
extern struct foo variable1;
extern struct foo variable2;
struct foo variable1 = { &variable2 };
struct foo variable2 = { &variable1 };
您的 TERM 宏不能在函数范围之外使用,因为它试图编写赋值而不是声明:
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; \
swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };
swizzle_tbl[__COUNTER__]
是赋值;你不能在函数之外进行赋值。它还必须升级以分配复合文字:
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; \
swizzle_tbl[__COUNTER__] = (swiz_ent){ &NAME, "NAME" };
在函数内部使用 TERM
可能有帮助也可能没有帮助;除非通过 swizzle_tbl
,否则无法在函数外部访问静态 cli_term
变量。这可能是一件好事。如果其他一切都没有问题(没有其他需要按名称访问数据),这应该没问题。
您需要考虑 __COUNTER__
的作用。它不是标准 C 的一部分,因此不可移植。您可以在函数中使用局部变量代替 __COUNTER__
.
我试图避免静态 table 中的一个问题,即一个 table 引用另一个引用原始 table 的问题。编译器抱怨找不到 table 成员之一的定义。为了解决这个问题,我一直在模拟一些测试代码,这些方法是否可行?像我正在尝试做的事情有可能吗?
以下代码供参考:
#define SWIZTBLMAX 256
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };
typedef struct cli_term
{
char* name;
cli_term* parent;
cli_term* child;
}cli_termt;
typedef struct swiz_ent
{
cli_term* t;
char* n;
}swiz_ent;
static swiz_ent swizzle_tbl[SWIZTBLMAX];
static cli_term* swizzle(const char* n)
{
int i;
for(i=0;i<SWIZTBLMAX;i++)
{
if(strcmp(n,swizzle_tbl[i].n)==0)
return swizzle_tbl[i].t;
}
return NULL;
}
TERM( ct_show_test, "test", swizzle("ct_show"), NULL )
TERM( ct_quit, "quit", NULL, NULL )
TERM( ct_show, "show", NULL, swizzle("ct_show_test") )
所以,我的想法是将指针分配推迟到运行时,我在将对象写入磁盘和写入磁盘时做了类似的事情。有什么办法可以像这样创建静态 table 吗? (带有指向静态分配的其他结构的指针)
您可以通过在定义变量之前声明变量来在全局变量中进行循环引用:
struct foo {
struct foo *fooptr;
};
extern struct foo variable1;
extern struct foo variable2;
struct foo variable1 = { &variable2 };
struct foo variable2 = { &variable1 };
您的 TERM 宏不能在函数范围之外使用,因为它试图编写赋值而不是声明:
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; \
swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };
swizzle_tbl[__COUNTER__]
是赋值;你不能在函数之外进行赋值。它还必须升级以分配复合文字:
#define TERM( NAME , ...) \
static cli_term NAME { __VA_ARGS__ }; \
swizzle_tbl[__COUNTER__] = (swiz_ent){ &NAME, "NAME" };
在函数内部使用 TERM
可能有帮助也可能没有帮助;除非通过 swizzle_tbl
,否则无法在函数外部访问静态 cli_term
变量。这可能是一件好事。如果其他一切都没有问题(没有其他需要按名称访问数据),这应该没问题。
您需要考虑 __COUNTER__
的作用。它不是标准 C 的一部分,因此不可移植。您可以在函数中使用局部变量代替 __COUNTER__
.