2012-09-20 53 views
0

在我們的代碼中,我們有一個混合類型的大結構,並且希望存儲這些的默認值的重複(const)結構。這是否與void *指針一起工作?如果沒有,如何?

當用戶想要默認一個設置時,最好能夠通過在結構中獲取該項目的地址偏移量來完成此操作,然後在「默認值」中指定具有相同偏移量的值結構,有點像這樣:

void *setting = &settings->thing; // Points to a setting 
int offset = setting - &settings; 
void *default = &defaults_struct + offset; // Points to the default value 
*setting = *default; // Set setting to default value 

的想法是,如果設置 - >東西指向一個INT8,該INT8值從默認值複製,但如果設置 - > other_thing是一個Int32,全32位被複制。

問題是,這是否可以像上面描述的那樣使用void指針?如果沒有,有沒有辦法做到這一點?我錯過了實現這一目標的更好方法嗎?

編輯澄清:我們想要將結構中的單個值設置爲「defaults」結構中的相應值。

+3

爲什麼不只是'settings-> thing = defaults_struct-> thing'? – interjay

+0

你不能在void指針上做指針運算,也不能像這樣通過它複製任何東西。您需要使用'char *'並找出適當的長度來複制(並自己複製)。 – Mat

+0

您應該使用'offsetof'宏來計算偏移量。 –

回答

6

不,這是行不通的。 void *類型的指針沒有與它們相關的大小,即它不知道它們指向哪種數據類型。因此,你也不能這樣做。

您應該直接從默認值中直接複製,如評論中所建議的那樣。

另請注意,default是C中的保留字,因此您不應將其用於變量。

如果默認值是全局可見,你可以定義一個宏來掩飾這一點:

#define INITIALIZE(s, f) s. f = default_struct. f 

用戶(我假設是開發者)現在可以做的:

struct settings s; 

INITIALIZE(s, thing); 

那說,我會(作爲開發者)喜歡這樣的東西:

struct settings s = get_default_settings(); 

這更清晰,更少魔法。當然,複製全部這些字段可能需要更多時間,但設置通常不會影響性能。

注意上面的功能可能只是:

struct settings get_default_settings(void) 
{ 
    static const struct settings the_defaults = {/* the default values go here*/}; 

    return the_defaults; 
} 

整齊地封裝的默認值,並刪除了全球。

+0

我可以看到複製了ENTIRE結構,我只想從結構中設置一個值而剩下的只剩下其餘部分。 –

1

C中沒有內置的運行時類型/反射信息。爲了執行您所要求的操作,您需要在運行時知道要複製的類型的實際大小。

如果你真的想這樣做,你在做什麼,你需要定義自己的運行時類型信息,通常通過使每個設定自己的..類似的結構......

struct single_setting { 
int stype; 
union { 
    uint8_t s8; 
    uint16_t s16; 
    uint32_t s32; 
    uint64_t s64; 
    struct { 
    char *s; 
    size_t len; 
    } sstr; 
} u_value; 
}; 

然後編寫一個函數來複制並返回這樣的值變得相當簡單。

如果您只想複製一些設置,但這幾乎是一些開銷,但幾乎是大型配置系統所做的。

+0

謝謝,爲每個設置添加元數據是我一直在玩的東西,但確實爲嵌入式系統增加了公平的開銷,尤其是在我們已經建立(需要更新的公平代碼庫)的情況下。 我喜歡每種設置都有「設置類型」結構的風格。 –

相關問題