5

Cで単純な動的配列を作成しました。

typedef struct varray_t
{
    void **memory;
    size_t allocated;
    size_t used;
    int index;              
} varray;

void
varray_init(varray **array)
{
    *array = (varray*) malloc (sizeof(varray));    
    (*array)->memory = NULL;
    (*array)->allocated = 0;
    (*array)->used = 0;
    (*array)->index = -1;
}

void
varray_push(varray *array, void *data, size_t size)
{
    if ((array->allocated - array->used) < size) {
        array->memory = realloc(array->memory, array->allocated + size);
        array->allocated = array->allocated + size;
    }

    array->used = array->used + size;   
    array->memory[++array->index] = data;
}

int
varray_length(varray *array)
{
    return array->index + 1;
}

void
varray_clear(varray *array)
{
    int i;
    for(i = 0; i < varray_length(array); i++)
    {
        array->memory[i] = NULL;
    }    
    array->used = 0;
    array->index = -1;
}

void 
varray_free(varray *array)
{
    free(array->memory);
    free(array);
}

void*
varray_get(varray *array, int index)
{
    if (index < 0 || index > array->index)
        return NULL;

    return array->memory[index];
}

これはうまくいっています。ただし、配列にアイテムを追加するには、呼び出し元は追加される要素のサイズを渡す必要があります。渡された からサイズを取得する別の方法がわかりませんvoid*。推測できるように設計varray_push(varray *array, void *data, size_t size)するためのより良い方法があるのではないかと思っていますか?size

どんな助けでも素晴らしいでしょう

提案後に編集されたコード

私の配列にはポインター要素のみが含まれます。Blastfurnace の提案に従ってコードを修正しました。新しいコードはsizeof(void*)、一定の割合でメモリを使用およびサイズ変更して、挿入時に償却された一定の時間を取得します。

void
varray_push(varray *array, void *data)
{
    size_t toallocate;
    size_t size = sizeof(void*);
    if ((array->allocated - array->used) < size) {
        toallocate = array->allocated == 0 ? size : (array->allocated * 2);
        array->memory = realloc(array->memory, toallocate);
        array->allocated = array->allocated + toallocate;
    }

    array->memory[++array->index] = data;
    array->used = array->used + size;
}
4

2 に答える 2

2

配列に一度に 1 つの型のみが含まれる場合は、配列の型のサイズを varray_init に格納できます。

また、私の提案は、要素ごとに新しいメモリを割り当てる代わりに、毎回一定のサイズのメモリを割り当てることができるということです。つまり、最初に 16 要素にメモリを割り当ててから、16 + 16 の要素 realloc をプッシュするときに配列がいっぱいになっていることがわかりました。 = 32 要素。このようにして、何度も malloc を呼び出すことを避けることができます。また、小さいサイズのデータ​​に対して個別に malloc を実行し続けるのは得策ではありません。

編集: Blastfurnace のコメントを検討した後、データへのポインターではなくデータを保存することが意図されている場合は、割り当てではなく、実際にデータの memcpy を実行する必要があると感じています。

于 2012-05-11T05:42:20.550 に答える
0

私は、あなたが使用できるリンクされたリストの実装を簡単に使用できます。テキストブックの品質とは言えませんが、簡単です: https://github.com/inorton/xrlist

#include <stdio.h>
#include "xrlist.h"

xr_list_t * mylist = xrlist_new();

xrlist_push(mylist, (void*) ptr1);
xrlist_push(mylist, (void*) ptr2);

あなたは次のように繰り返します:-

xr_list_item_t * iter = mylist->head;
while ( iter != NULL ) 
{
  printf(" * item [0x%x] contains [%s]\n",
    (unsigned int) iter->object, (char*) iter->object );
  iter = iter->next; 
}

また、通常の削除/追加/解放機能もあります。ここで他の例を参照してください。

辞書のようなランダムアクセスデータが必要な場合は、 https://github.com/inorton/xrhashを試すこともできます

于 2012-05-11T06:19:13.710 に答える