簡體   English   中英

在C中評估結構成員訪問的功能指針?

[英]Evaluate a Function Pointer on Structure Member Access in C?

我有一個問題要解決,如果我可以讓一個結構的成員在訪問時對函數的結果求值,那基本上就消失了。 我認為我從未見過此類行為的任何示例-實際上,我懷疑如果不進行一般編程,我所尋找的內容將違反一些深層的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
}

因為函數指針將是一個常量表達式。 但是,當我寫下來時,我的心func_to_get_foo ,因為我意識到,現在當然baz只是指向func_to_get_foo的指針,而不是我幻想的foo值。

我正在使用的實際程序非常復雜,而且我仍在學習它的來龍去脈。 我希望在獲得多狀態功能的同時進行盡可能少的修改。 初始化程序列表變量有很多實例,例如bar示例,因此我寧願避免為每個實例編寫上下文切換代碼。

因此,如果有某種魔術可能導致由於訪問bar.baz而導致func_to_get_foo()的結果出現,我會欣喜若狂。 有人對如何輕松完成此操作有任何建議嗎?

如果沒有辦法做到這一點,那么我當然很想聽聽一些關於為什么的理論……或者它是干切的“那不是C的功能嗎?”

最后,如果沒有聰明的竅門,那么根據當前狀態更改這些變量的正確方法是什么? 我是否需要編寫一個函數來設置每次上下文更改的每個函數?

假設我正確地遵循了這一點, 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初始值設定項進行了初始化,否則此技術完全不可靠。 屬性初始化程序確實按順序運行,但這不是您想要的順序。 在第二種情況下,我們必須進一步依靠gcc的擴展來復制c++iostream魔術,如下所示:

attribute((constructor))
static void init_bar(){
    init_state();
    bar.baz = func_to_get_foo();
}

/* ... */

state_t state;
static char state_initialized;
attribute((constructor))
void init_state()
{
    if (state_initialized) return;
    state_initialized = 1;
    /* do whatever to fill out state */
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM