2011-01-26 11 views
3

ページの最後に質問が返されました。フルワーキングコード。C自動拡張可能なポインタ配列

こんにちは、私はタイトルで尋ねたことはCでしたいと思いますが、それを達成する方法はわかりません。テンプレートのおかげでC++でこれをやったことがありますが、àla Cです。ここには完全に機能するC++コードがあります:List.h (simple database)

* 私はコードをエミュレートすることができますかどうか私は今疑問に思っています。問題は、ボイド*が解決できないほどのトラブルを引き起こす可能性があるため、回避すべきというリンクを見たことです。

基本的には、変数自体へのポインタを格納する「スマートアレイ」です。 各ポインタのサイズと各構造体のサイズがわかっていれば、単純なmallocとreallocは正しく動作するはずですか?

typedef struct 
{ 
    void **list; 

    // internal 
    int last_item_index; 
    size_t element_size; // size of each pointer 
    int elements;  // number of currently allocated elements 
    int total_size;  // >= #elements so that we don't have to always call malloc 
    int tweak_request_size; // each time the list grows we add this # of elements 

} List; 
// a shot at an addCopy function 
// it deepcopies the object you pass in 
List_addCopy(List *db, void *ptr_to_new_element) 
{ 
    ... // grow **list 
    // alloc and copy new element 
    db->list[db->last_item_index+1] = malloc(element_size); // WORKS? 
    // HOW TO COPY THE ELEMENT TO HERE IF IT IS A STRUCTURE FOR INSTANCE??? 
    ... 
} 

or 
// a shot at an assign function 
// (allocate the elements yourself then pass the pointer to the List) 
List_assign(List *db, void *ptr_to_new_element) 
{ 
    db->List = realloc(db->List, element_size*(elements+tweak_request_size)); 
    db->List[db->last_item_index+1] = ptr_to_new_element; 
} 

// Usage example 

List db; // our database 
struct funky *now = (funky*)malloc(sizeof(funky)); 

funky->soul = JamesBrown; 

List_addCopy(db, funky); 

if (list[0]->soul == JamesBrown) 
    puts("We did It! :D"); 

私は外にすべてをALLOCとちょうど私が唯一の問題は**無効と推測リストへのポインタを渡す場合。

リストア可能ですか?要素のアロケートやコピーを行うコールバックでのみですか?

List_assignは可能ですか?私は多くの仕事をして、信頼できないソフトウェアで終わらせたくありません。

どうもありがとうと書面での畳み込みのため申し訳ありません:P

+0

要素のサイズを知っていて、単純なフラットなデータ構造(コピーする必要のあるものへのポインタはありません)の場合は、それを上書きするだけです。 –

+0

@Pemdas:私はそれについて言及したと信じています。 –

+0

それは問題にならないでしょうか? void * * *を使用していますか?私は結果が混在する可能性があるので、void * * *を避けるべきだと言っているスレッドを見た:http://c-faq.com/ptrs/genericpp.htmlありがとう – Alberto

答えて

1

あなたはこのようなものでvoid*を避けることができます。

#include <stdio.h> 
#include <stdlib.h> 

#define List(T) \ 
    typedef struct { \ 
     T** items; \ 
     int count; \ 
    } List_ ## T ;\ 
    \ 
    List_ ## T * List_ ## T ## _New() { \ 
     List_ ## T * list = (List_ ## T *) malloc(sizeof(List_ ## T)); \ 
     list->count = 0; \ 
     return list; \ 
    } \ 
    \ 
    void List_ ## T ## _Add(List_ ## T *list, T * data) { \ 
     printf("%d\n", ++list->count); \ 
    } \ 
    void List_ ## T ## _Del(List_ ## T *list, int index) { \ 
     printf("%d\n", --list->count); \ 
    } 

/* define just one list per type */ 
List(int); 
List(double); 

int main() 
{ 
    int a, b, c; 
    double d, e; 
    List_int *l1; 
    List_double *l2; 

    l1 = List_int_New(); 
    List_int_Add(l1, &a); 
    List_int_Add(l1, &b); 
    List_int_Add(l1, &c); 
    List_int_Del(l1, 0); 
    List_int_Del(l1, 0); 
    List_int_Del(l1, 0); 

    l2 = List_double_New(); 
    List_double_Add(l2, &d); 
    List_double_Add(l2, &e); 
    List_double_Del(l2, 0); 
    List_double_Del(l2, 0); 

    return 0; 
} 

貧乏人のテンプレートだ=)

神が祝福

+0

ありがとう!私は考えがありました。使用するのは非常に簡単ですが、実装するのは苦痛ですが、一度だけしなければならないのでうまくいくと思います) – Alberto

+0

私はそれが難しいとは思わない、 # 'と' \ '。それをデバッグし、コンパイル時のエラーを追跡することは難しいかもしれません。私は、 'List_int'のように実装し、最初にテストし、それを"テンプレート "にする方が良いと思います。このアプローチのもう一つの問題は、リスト型のパラメータをポインタにすることができないということです。プロシージャ名を生成するとき、コンパイラは '*'を含む名前を好まないのですが、ポインタを暗黙的にすることによって回避できます。 – Trinidad

1

フル稼働コード

こんにちは、私は**うまくいくのボイドわからなかったし、それはかなりいいのxD

それは完璧に動作しますので、トリニダードのメソッドを使用しましたが、それは結果、別のヘッダーを含む循環依存関係を(避けるために複雑になっています私はそれを@SourceForgeでもアップロードしましたが、私はこのアプローチをあきらめましたが、voidポインタを使ってすべてを再作成しました。これは完全に動作します;)ヘッダーを2回など、ちょうどうまくいきます。

ところで、ここにリンクがあなたの好みでそれを使用して、です:私は、私はそれを文書化します時間がある時に何の疑いでList - the smart && generic container

は、ヘルプフォーラムを使用しますが、今のところ、私は私のプロジェクトのためにそれを使用しています。

幸運を祈る!

関連する問題