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数组,并且稍后转换为所需类型将执行此工作,但对于稍后将阅读此代码的人来说可能会非常混乱.
嗯,有点,但它可能不是你想要的东西:
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)
我可能会这样做:
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 进行类型转换。和/或使用联合来不必进行类型转换。