void类型的数组

S.J*_*.J. 12 c arrays void-pointers

plain C有很好的功能 - void类型指针,可以用作指向任何数据类型的指针.
但是,假设我有以下结构:


struct token {
    int type;
    void *value;
};
Run Code Online (Sandbox Code Playgroud)

其中value字段可以指向char数组,或指向int或其他内容.
所以在分配这个结构的新实例时,我需要:

1)为这个结构分配内存;
2)为值分配内存并将其分配给值字段.

我的问题是 - 有没有办法声明" 类型为void的数组 ",它可以被转换为任何其他类型,如void指针?

我想要的只是使用"灵活的成员阵列"(在C99标准的6.7.2.1中描述),能够投射到任何类型.

像这样的东西:


struct token {
    int type;
    void value[];
};

struct token *p = malloc(sizeof(struct token) + value_size);
memcpy(p->value, val, value_size);
...
char *ptr = token->value;

Run Code Online (Sandbox Code Playgroud)

我假设将token-> value声明为char或int数组,并且稍后转换为所需类型将执行此工作,但对于稍后将阅读此代码的人来说可能会非常混乱.

Chr*_*utz 5

嗯,有点,但它可能不是你想要的东西:

struct token {
  // your fields
  size_t item_size;
  size_t length
};

struct token *make_token(/* your arguments */, size_t item_size, size_t length)
{
    struct token *t = malloc(sizeof *t + item_size * length);
    if(t == NULL) return NULL;
    t->item_size = item_size;
    t->length    = length;
    // rest of initialization
}
Run Code Online (Sandbox Code Playgroud)

以下宏可用于索引您的数据(假设x是 a struct token *):

#define idx(x, i, t) *(t *)(i < x->length ? sizeof(t) == x->item_size ?
                       (void *)(((char *)x[1]) + x->item_size * i)
                     : NULL : NULL)
Run Code Online (Sandbox Code Playgroud)

而且,如果您愿意,以下宏可以包装您的make_token函数,使其更直观(或者更黑客,如果您这样想的话):

#define make_token(/* args */, t, l) (make_token)(/* args */, sizeof(t), l)
Run Code Online (Sandbox Code Playgroud)

用法:

struct token *p = make_token(/* args */, int, 5); // allocates space for 5 ints
...
idx(p, 2, int) = 10;
Run Code Online (Sandbox Code Playgroud)


old*_*mer 1

我可能会这样做:

struct token {
    int type;
    void *value;
};

struct token p;

p.value = malloc(value_size);

p.value[0] = something;
p.value[1] = something;
...
Run Code Online (Sandbox Code Playgroud)

编辑,实际上你必须对这些 p.value[index] = somes 进行类型转换。和/或使用联合来不必进行类型转换。

  • 这甚至无法编译。一些编译器允许对“void *”指针进行指针算术(作为扩展),但所有编译器都禁止取消引用 void 指针。 (3认同)