2011-04-25 130 views
6

plain C具有很好的特性 - void類型指針,可用作指向任何數據類型的指針。
但是,假設我有以下結構:數組類型void


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

其中value字段可能指向字符數組,或爲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; 

我想令牌的聲明>值作爲char或int數組和鑄造所需類型以後會做這項工作,但可以非常混亂的人誰都會閱讀代碼稍後。

+0

雙指針? – 2011-04-25 22:06:39

+2

使用'char []'是好的恕我直言,因爲'sizeof(char)== 1',你永遠不會感到驚訝。您可能需要考慮宏以正確的類型訪問'p-> value'。 – 2011-04-25 22:20:51

回答

1

我可能會做這樣的:

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

struct token p; 

p.value = malloc(value_size); 

p.value[0] = something; 
p.value[1] = something; 
... 

編輯,其實你必須強制轉換的p.value [指數] =出頭。和/或使用工會不必強制轉換。

+0

在使用之前,您必須先施放'p.value'。 – 2011-04-25 22:11:01

+0

'p.value [0] = something'會產生編譯時錯誤,當然?人們不能解除引用「void *」。 – 2011-04-25 22:12:05

+0

咧嘴笑,你打我吧...試圖迅速得到編輯。 – 2011-04-25 22:12:16

3

嗯,有點,但它可能不是你想要的東西:

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 
} 

下面的宏可以用來索引數據(假設xstruct 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) 

而且,如果你喜歡,下面的宏可以包裝你的make_token函數,使它更直觀一點(或者如果你這麼想的話,會更加黑客):

#define make_token(/* args */, t, l) (make_token)(/* args */, sizeof(t), l) 

用法:

struct token *p = make_token(/* args */, int, 5); // allocates space for 5 ints 
... 
idx(p, 2, int) = 10; 
1

你不能有「無效」項的數組,但你應該能夠做到像你想要什麼,只要你知道,當你做value_size malloc的。但它不會很漂亮。

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

value_size = sizeof(type)*item_count; 
struct token *p = malloc(sizeof(struct token) + value_size); 
//can't do memcpy: memcpy(p->value, val, value_size); 
//do this instead 
type* p = (type*)&(p->value); 
type* end = p+item_count; 
while (p<end) { *p++ = someItem; } 

請注意,當您想要獲得額外的存儲空間時,您需要額外的地址運算符。

type *ptr = (type*)&(token->value); 

這將「浪費」的sizeof(void *的)字節,原始類型的value其實並不重要,所以你不妨使用一個較小的項目。我可能typedef char placeholder;,並使value這種類型。

0

以下結構可以幫助你。

struct clib_object_t { 
void* raw_data; 
size_t size; 
}; 

struct clib_object_t* 
new_clib_object(void *inObject, size_t obj_size) { 
    struct clib_object_t* tmp = (struct clib_object_t*)malloc(sizeof(struct clib_object_t)); 
    if (! tmp) 
     return (struct clib_object_t*)0; 
    tmp->size  = obj_size; 
    tmp->raw_data = (void*)malloc(obj_size); 
    if (!tmp->raw_data) { 
     free (tmp); 
     return (struct clib_object_t*)0; 
    } 
    memcpy (tmp->raw_data, inObject, obj_size); 
    return tmp; 
} 

clib_error 
get_raw_clib_object (struct clib_object_t *inObject, void**elem) { 
    *elem = (void*)malloc(inObject->size); 
    if (! *elem) 
     return CLIB_ELEMENT_RETURN_ERROR; 
    memcpy (*elem, inObject->raw_data, inObject->size); 

    return CLIB_ERROR_SUCCESS; 
} 

更多詳細信息:clibutils

0

擴展在AShelly的答案,你可以做到這一點;

/** A buffer structure containing count entries of the given size. */ 
typedef struct { 
    size_t size; 
    int count; 
    void *buf; 
} buffer_t; 

/** Allocate a new buffer_t with "count" entries of "size" size. */ 
buffer_t *buffer_new(size_t size, int count) 
{ 
    buffer_t *p = malloc(offsetof(buffer_t, buf) + count*size); 
    if (p) { 
     p->size = size; 
     p->count = count; 
    } 
    return p; 
} 

注意分配,以避免浪費內存時使用 「offsetof()」 而不是 「的sizeof()」, 「無效* BUF;」字段大小。 「buf」的類型並不重要,但使用「void *」意味着它將對結構中的「buf」字段進行最佳對齊,並在需要時在其之前添加填充。這通常會爲條目提供更好的內存對齊,特別是如果它們至少與指針一樣大。

訪問緩衝區中的條目如下所示;

/** Get a pointer to the i'th entry. */ 
void *buffer_get(buffer_t *t, int i) 
{ 
    return &t->buf + i * t->size; 
} 

注意額外地址的運營商獲得「BUF」域的地址作爲起點分配的條目存儲。

相關問題