开发者

C automatic-expandable array of pointers

开发者 https://www.devze.com 2023-02-06 23:08 出处:网络
QUESTION ANSWERED AT END OF PAGE. FULLY WORKING CODE. Hello, I would like to do in C what I have asked in the title, however, I don\'t know how to accomplish it. I have done this in C++ thanks to tem

QUESTION ANSWERED AT END OF PAGE. FULLY WORKING CODE.

Hello, I would like to do in C what I have asked in the title, however, I don't know how to accomplish it. I have done this in C++ thanks to templates but à la C. Here is the fully functional C++ code: List.h (simple database)

*I wonder now if with void pointers I can emulate the code. The problem is that I've seen a link stating that void * should be avoided because it can cause more trouble than it can solve.

Basically it is a "smart-array" that stores pointers to the variables themselves. If I know the size of each pointer and the size of each structure pointed to, simple mallocs and reallocs should do right?

typedef struct
{
  void **list;

  // internal
开发者_如何学Python  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");

If I alloc everything outside and just pass the pointers to the List I guess the only problem is the void **.

Is List_add possible? Only with callbacks that do the alloc of the element and / or copy it?

Is List_assign possible? I don't want to have a lot of work and end up with unreliable software.

Thanks a lot and sorry for the convolution in the writing :p


You can avoid void* with something like this:

#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);
    free(l1);

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

    return 0;
}

That's a poor man's template =)


I've used Trinidad's method since I wasn't sure void ** would work and it's pretty nice xD

It works perfectly but it is complicated to avoid circular dependencies (including a header in another that results in "multiple reference") without encumbering too much the interface, so I gave up that approach although I've uploaded it too @SourceForge, then I made everything again, this time with void pointers and it works perfectly ;) No worrying about including a header twice, etc. Just works.

Btw, here's the link, use it at your liking: List - the smart && generic container

In any doubt use the help forums, when I have time I'll document it, but for now I'm using it for my projects.

0

精彩评论

暂无评论...
验证码 换一张
取 消