2014-12-31 128 views
0

假設你有這樣的結構:鑄造指向struct的指針與const成員爲結構

struct nix_codec { 
    nix_uint8 state; 
    nix_uint8 mode; 
    nix_uint8 flags; 
    nix_size offset; 
    nix_uint32 codepage; 
    nix_utf8 const *const *aliases; 
    void (*delete)(
     struct nix_codec *codec, 
     struct nix_error *error 
    ); 
    struct nix_codec* (*clone)(
     struct nix_codec const *codec, 
     nix_int8 mode, 
     struct nix_error *error 
    ); 
    nix_size (*decode)(
     struct nix_codec *codec, 
     nix_byte const *bdata, 
     nix_size bsize, 
     nix_rune *udata, 
     nix_size usize, 
     struct nix_error *error 
    ); 
    nix_size (*encode)(
     struct nix_codec *codec, 
     nix_rune const *udata, 
     nix_size usize, 
     nix_byte *bdata, 
     nix_size bsize, 
     struct nix_error *error 
    ); 
}; 

typedef struct { 
    nix_uint8 const state; 
    nix_uint8 const mode; 
    nix_uint8 const flags; 
    nix_size const offset; 
    nix_uint32 const codepage; 
    nix_utf8 const *const *const aliases; 
} nix_codec; 

人們也有多種功能,其被用於創建nix_codec*情況下,例如爲UTF-8編碼解碼器它看起來就像這樣:

static nix_size self_decode 
(
    struct nix_codec *codec, 
    nix_byte const *bdata, 
    nix_size bsize, 
    nix_rune *udata, 
    nix_size usize, 
    struct nix_error *error 
) 
{ /* UTF-8 decode function, too long to post here */} 

static nix_utf8 const *const aliases[] = { 
    "UTF-8", 
    "UTF8", 
    "CP65001", 
    NULL, 
}; 

nix_codec *nix_codec_utf8 
(
    nix_int8 mode, 
    struct nix_error *error 
) 
{ 
    struct nix_codec *codec = NULL; 

    if ((mode != NIX_CODEC_STRICT) && (mode != NIX_CODEC_ESCAPE) 
    && (mode != NIX_CODEC_REPLACE) && (mode != NIX_CODEC_IGNORE)) { 
     return NULL; 
    } 
    codec = calloc(1, sizeof(struct nix_codec)); 
    if (codec == NULL) { 
     return NULL; 
    } 
    codec->mode = mode; 
    codec->codepage = 65001; 
    codec->aliases = aliases; 
    codec->decode = &self_decode; 
    codec->encode = &self_encode; 
    codec->flags = (NIX_CODEC_COMPATIBLE | NIX_CODEC_MULTIBYTE | NIX_CODEC_ABSOLUTE); 
    return (nix_codec*)codec; 
} 

對於傳統的單字節編碼的功能是基於這樣的結構:

struct nix_sbmap { 
    nix_uint8 byte; 
    nix_rune rune; 
}; 

struct nix_sbcodec { 
    struct nix_codec base; 
    struct nix_sbmap const *entries; 
    nix_size count; 
}; 

注意struct nix_sbcodecstruct nix_sbmap在源文件中的聲明,而不是在標題中,因此不需要使用variant模式。相應的功能,例如nix_codec_koi8r(),分配struct nix_sbcodec,設置其base,entriescount成員,然後將其轉換爲nix_codec並將其返回。每一個實際encode()decode()呼叫使用這個公共函數執行:

nix_size nix_codec_decode 
(
    nix_codec *codec, 
    nix_byte const *bdata, 
    nix_size bsize, 
    nix_rune *udata, 
    nix_size usize, 
    struct nix_error *error 
) 
{ 
    nix_size result = 0; 
    struct nix_codec *self = (struct nix_codec*)codec; 

    return self->decode(self, bdata, bsize, udata, usize, error); 
} 

注意statemodeflagsoffset成員可能是有趣的,使用任何編解碼器的人(其中大部分是在編解碼器的創造者的功能設置,offset被調用encode()decode()功能改變後,代表功能退出之前其已成功處理的字節/ Unicode字符數。每個編解碼器都有自己的encode()decode()功能,當你看到。

現在的問題是:這個技巧是否正確並保證可以在C標準下工作?

在此先感謝!

+2

什麼問題? – IdeaHat

+0

'class'?在'c'中? –

+0

這是C不是C++吧?你爲什麼做這個?這坦率地說是一個等待發生的事故。如果你將一個'my_object'賦給另一個,你期望編譯器做什麼? (提示:'memcpy(b,a,sizeof(my_object)') –

回答

0

處理C中變體類型的可靠方法,比如我認爲你正在嘗試的方法是使用union。例如:

typedef struct { 
    uint8_t x; 
    uint16_t y; 
} obj_a; 

typedef struct { 
    char *p; 
    char buf[42]; 
} obj_b; 

typedef struct obj_base_s { 
    int (*internal_func)(struct obj_base_s *, int); 
    union { 
     obj_a a; 
     obj_b b; 
    } u; 
} obj_base; 

所有創作者/析構函數將返回或使用obj_base。 ,在union使用成員函數既可以訪問其位直接別的做這樣的事情:

void handle_obja(obj_base *bp) 
{ 
    obj_a *oap = &bp->u.a; 
    oap->x = 23; 
    oap->y = 19; 
    ... 
} 

C是 C++,如果你想很好的類,繼承,重載和所有的東西,然後用C++ 。這是爲什麼C++被髮明的主要原因。 C不會做「課程」。 C是一種低得多的語言。

+0

'Variant'模式在這裏不適用。我正在談論繼承,但可能會有很多繼承'my_object'的結構,並且我沒有看到將每個'variant'放入'my_object'聲明中的好處。 – ghostmansd

+0

查看更新的帖子。希望它能澄清事情。 – ghostmansd

+0

C沒有任何繼承的概念。最終,爲了模仿C++繼承,您或者擁有一個大的結構,您可以將程序員分成與不同功能集相關的塊。或者你使用不同的結構,並且(以這種或那種方式)將void指針傳遞給這些結構。但是模仿C++就是你正在做的事情。如果你能找到'cfront'的工作副本,你可能會對它的輸出感興趣。這是C++在編譯之前最初是如何在C中預處理的。 IIRC它爲每個班級創建了一個大型結構。 –

0

注意statemodeflagsoffset成員可能 有趣的使用任何編解碼器(...

現在的問題的人:是這招正確,並保證由 C標準的工作?

然而有用它可以是與然而常常它可能工作,這招(由一個指針指向一個訪問struct nix_codec對象的成員不同的定義nix_codec對象)是不安全的,除非你斷言兩者的對應的構件結構類型在結構中具有相同的偏移量;這不能保證獨立定義的結構類型;這樣的保證僅存在於結構的工會 - 見語言/表達式/後綴運算符/結構和工會成員 /第6款:

一個特殊的保證,以便作出簡化聯合的使用:如果一個聯合包含共享一個公共初始序列的多個結構(見下文),並且聯合對象當前包含這些結構中的一個,則允許檢查共同的 中的任何一個的初始部分他們在任何地方宣佈工會 的完成類型是可見的。如果對應的成員 對於一個或多個初始成員的序列具有兼容的類型(並且對於位域,具有相同的寬度),則兩個結構共享共同的初始序列