Thread: Vector container in C

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    5

    Vector container in C

    I want to complete a vector container in C. I have the following function add_element() and i want to pass it a 'type' argument which is the type of the argument for data. How can this be done?

    it would be something like:
    Code:
    void add_element(Vector *v, void * data, type ){
        type *p = (type *)malloc(sizeof(type) * (v->length+1));
        int i;
        for (i = 0; i < v->length ; i++){
            p[i] = v->pvector[i];
        }
        p[i] = *data;
        free(v->pvector);
        v->pvector = p;
        v->length++;
    }

  2. #2
    The larch
    Join Date
    May 2006
    Posts
    3,573
    I believe in C you'd rather pass sizeof(type) to the function.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  3. #3
    Registered User
    Join Date
    Apr 2009
    Posts
    5
    i've found this code for preprocessor that does what i want
    Code:
    #define swap(_a,_b,_type)\
    {\
      _type _tmp;\
      \
      _tmp = (_a);\
      (_a) = (_b);\
      (_b) = _tmp;\
    }
    isn't there a way to pass the type of the data as an argument to a function?

  4. #4
    The larch
    Join Date
    May 2006
    Posts
    3,573
    A macro would be possible. (Note that in C one would use realloc instead of alloc + copy + free.)

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    #define ADD_ELEMENT(vec, value, type) \
        do { \
            type *p = realloc((vec)->pvector, sizeof(type) * ((vec)->length+1)); \
            if (p) { \
                p[(vec)->length] = (type)(value); \
                (vec)->length++; \
                (vec)->pvector = p; \
            } \
        } while (0)
    
    typedef struct
    {
        int length;
        void* pvector;
    } Vector;
    
    
    int main(void)
    {
        int n = 42;
        Vector vec;
        vec.length = 0;
        vec.pvector = NULL;
    
        ADD_ELEMENT(&vec, n, int);
        ADD_ELEMENT(&vec, 666, int);
        printf("Successfully added %d and %d\n", ((int*)(vec.pvector))[0], ((int*)(vec.pvector))[1]);
        return 0;
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    And if you want it to be at least a little bit efficient, I would not use realloc on every single call. Have a third element in the struct, which holds the size of the vector, and let it grow by X number of cells each time (where X is either a constant >= 1, or a multiplier, e.g. 1.5 * current lenght).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Perhaps another option would be to turn the entire implementation into a macro, so you can create all the "instantiations" that you want.

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <assert.h>
    
    #define USE_VECTOR_OF(type) \
    typedef struct \
    { \
        int length; \
        type* buffer; \
    } vector_##type; \
    \
    vector_##type create_vector_##type(void) \
    { \
        vector_##type vec = {0, 0}; \
        return vec; \
    } \
    \
    int add_##type(vector_##type* vec, type value) \
    { \
        type* p = realloc(vec->buffer, vec->length * sizeof(type)); \
        if (p) { \
            vec->buffer = p; \
            vec->buffer[vec->length] = value; \
            ++vec->length; \
            return 1; \
        } \
        return 0; \
    } \
    \
    type get_##type(const vector_##type* vec, int index) \
    { \
        assert(index >= 0 && index < vec->length); \
        return vec->buffer[index]; \
    }
    
    #define Vector(type) vector_##type
    #define Vcreate(type) create_vector_##type()
    #define Vadd(type, vec, val) add_##type(vec, val)
    #define Vget(type, vec, index) get_##type(vec, index)
    
    USE_VECTOR_OF(int)
    USE_VECTOR_OF(double)
    
    int main(void)
    {
        {
            Vector(int) vec = Vcreate(int);
            if (!Vadd(int, &vec, 42)) return -1;
            if (!Vadd(int, &vec, 100)) return -1;
            printf("added: %d %d\n", Vget(int, &vec, 0), Vget(int, &vec, 1));
        }
        {
            Vector(double) vec = Vcreate(double);
            if (!Vadd(double, &vec, 15.75)) return -1;
            if (!Vadd(double, &vec, -21.123)) return -1;
            printf("added: %f %f\n", Vget(double, &vec, 0), Vget(double, &vec, 1));
        }
        return 0;
    }
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed