在C中评估结构成员访问的功能指针?

时间:2019-03-11 00:47:30

标签: c patch theory

我有一个要解决的问题,如果我可以让一个结构的成员在访问时对函数的结果求值,那基本上就消失了。我认为我从未见过此类行为的任何示例-实际上,我怀疑如果不进行一般编程,我所寻找的内容将违反一些深层的C规则。如果是这样,我当然会很高兴听到有更多证据/经验的人来解释为什么。

这里有一些简化的代码作为示例:

/* state.c */

#include "state.h"

state_t state_ctx;
/* state.h */

typedef struct _state_t {
    foo_t foo;
}state_t;

extern state_t state_ctx;

#define ACCESS_STATE(x) (state_ctx.x)
/* main.c */

const bar_t bar{
    .baz = ACCESS_STATE(foo); // Types are compatible
}

英语中有一个全局状态变量,它具有重新定义访问权限的便捷方法,并且该访问方法用于感兴趣的.c文件中全局变量的初始化列表内。

该代码有效,但是我的任务是允许将上下文从一个状态变量切换到另一个状态变量。我可以轻松地将状态定义更改为:

/* state.c */

#include "state.h"

state_t* p_current_state_ctx; // Now a pointer id's the current state structure
/* state.h */

typedef struct _state_t {
    baz_t foo;
}state_t;

extern state_t* p_current_state_ctx;

#define ACCESS_STATE(x) (p_current_state_ctx->x)

切换上下文所需要做的就是设置当前状态指针。真好但是有一个问题-初始化程序列表需要ACCESS_STATE(x)宏才能将其求值为常量。我认为定义这样的函数很棒:

foo_t func_to_get_foo( void ){
    return p_current_state_ctx->foo;
}

这样main.c初始化程序可以重写为:

/* main.c */

const bar_t bar{
    .baz = (foo_t)&func_to_get_foo; // Trying to get current state's foo
                                    // Obviously this cast isn't generally correct
                                    // and only compiles if the types are pointers
                                    // but still the behavior is wrong
}

因为函数指针将是一个常量表达式。但是,当我写出它时,我的心然,因为我意识到现在baz当然只是func_to_get_foo的指针,而不是我幻想的foo的值。

我正在使用的实际程序非常复杂,而且我仍在学习它的来龙去脉。我希望在获得多状态功能的同时进行尽可能少的修改。初始化列表变量有很多实例,例如bar示例,所以我宁愿避免为每个变量编写上下文切换代码。

因此,如果存在一些魔术,这些魔术可能会导致func_to_get_foo()的结果作为访问bar.baz的结果,我会欣喜若狂。有人对如何轻松完成此操作有任何建议吗?

如果没有办法做到这一点,那么我当然很想听听一些有关为什么的理论……或者它是干切的“那不是C的功能吗?”

最后,如果没有聪明的窍门,那么更改这些依赖于当前状态的变量的正确方法是什么?我是否需要编写一个函数来设置每个变量?时间何时改变?

1 个答案:

答案 0 :(得分:0)

假设我正确地遵循了这一点,section:first-of-type > header > h2 { color: red; }是一个全局变量,而<section> <header> <h2>One</h2> </header> </section> <section> <header> <h2>Two</h2> </header> </section>不是可以手动折叠的东西。确实确实使它变得困难。实际上,无法通过可移植的bar代码来做到这一点。在过去,我们将这些东西放到func_to_get_foo的早期,效果很好。

有了c,我们现在可以使用main()

gcc

要小心;仅当attribute((constructor))已使用bar_t bar; /* cannot declare this const as this might place it in readonly memory */ attribute((constructor)) static void init_bar(){ bar.baz = func_to_get_foo(); } 初始化程序初始化时,此方法才有效,否则此技术完全不可靠。属性初始化程序确实按顺序运行,但这不是您想要的顺序。在第二种情况下,我们必须进一步依靠state_t state_ctx;的扩展名来复制const的{​​{1}}魔术,如下所示:

gcc