2014-12-31 185 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款:

一个特殊的保证,以便作出简化联合的使用:如果一个联合包含共享一个公共初始序列的多个结构(见下文),并且联合对象当前包含这些结构中的一个,则允许检查共同的 中的任何一个的初始部分他们在任何地方宣布工会 的完成类型是可见的。如果对应的成员 对于一个或多个初始成员的序列具有兼容的类型(并且对于位域,具有相同的宽度),则两个结构共享共同的初始序列