-1

I am trying to copy a void pointer to different indexes of another pointer array, things work fine for characters but there appears problem for integer and doubles

Here is my strcture:

typedef struct vector_struct {
 size_t e_sz;
 char e_type;

 #define V_INT 1 
 #define V_DOUBLE 2
 #define V_CHAR 3

 unsigned no_e;
 unsigned cur_cap;
 void* e_array;

}* vector_type;
 //for typecasting
  #define vector_int_at(v,i) (*((int*)v_at(v,i)))
  #define vector_double_at(v,i) (*((double*)v_at(v,i)))
  #define vector_char_at(v,i) (*((char*)v_at(v,i)))

  void* v_at(vector_type v, iterator i) {
    if ( v == NULL )
     fail("v_at() Error: no such vector");
    if ( i == iterator_end )
     i = v->no_e -1;
    if ( i < 0 || i >= v->no_e )
     fail("v_at() Error: no such element in this vector");
    return (v->e_array+i); //return element
   }

I want to copy value into the void* e_array , it can be either integer, character or a double.

void v_push_back(vector_type v, void* new_val){
 if ( v->no_e >= v->cur_cap ) {
    /*** need to expand the array ***/
    v->cur_cap += (v->cur_cap)? v->cur_cap : 2;

    v->e_array = check_a(realloc(v->e_array, sizeof(void*) * v->cur_cap));
    //allocate memory

   }
/*** copy new_val into the array at end position (v->no_e) ***/
   printf("%d  %d %p\n",v->e_sz,v->no_e,v->e_array+(v->no_e *v->e_sz));
    memcpy(
          v->e_array +(v->no_e)*v->e_sz,
          new_val,
          v->e_sz
          );

 (v->no_e)++;
}

I have called this function like this:

c1 = 'o'; v_push_back(vc1,(void*)&c1); //for character
for ( i1 = 0 ; i1 < 10 ; i1++ ){ //for integer
    v_push_back(vi1,(void*)&i1);
}

//I call these like
  for ( i1 = 0 ; i1 < vector_size(vi1) ; i1++ )
   printf(" %ld",vector_int_at(vi1,i1));
  printf("\n");

But it seems things doesn't work for integer but works well for characters but for integers garbage values are copied as shown: enter image description here

Please help me out. thanks

Here the complete project: https://s3.amazonaws.com/assignment.pointers.vectorc.implementation/C-VectorImplementation1.zip

Faizan Shah
  • 123
  • 10
  • When reading, do you cast `e_array`? If yes how? – Phantom May 09 '19 at 12:50
  • Provide a [mcve]. – Eric Postpischil May 09 '19 at 12:50
  • You're probably not taking account of the size of what your void pointer points to. Anyway please provide a [mcve]. – Jabberwocky May 09 '19 at 12:51
  • #define vector_int_at(v,i) (*((int*)v_at(v,i))) #define vector_double_at(v,i) (*((double*)v_at(v,i))) #define vector_char_at(v,i) (*((char*)v_at(v,i))) – Faizan Shah May 09 '19 at 12:53
  • 2
    @FaizanShah: Do not put code in comments. Edit the question to contain a [mcve]. – Eric Postpischil May 09 '19 at 12:55
  • You are always allocating `sizeof(void *)` -- `v->e_array = check_a(realloc(v->e_array, sizeof(void*) * v->cur_cap));` perhaps you want `v->e_array = check_a(realloc(v->e_array, v->e_sz * v->cur_cap));` size of current vector. – kiran Biradar May 09 '19 at 13:00
  • 1
    Please provide a [mcve] (emphasis on _complete_). Something that can be copy/pasted and compiled. – Jabberwocky May 09 '19 at 13:03
  • @FaizanShah what is the `v_at` function? (And yes, edit you question!) – Phantom May 09 '19 at 13:22
  • here is the path to actual project: https://s3.amazonaws.com/assignment.pointers.vectorc.implementation/C-VectorImplementation1.zip – Faizan Shah May 09 '19 at 13:26
  • @Phantom edited – Faizan Shah May 09 '19 at 13:28
  • @FaizanShah No one is going to follow a link to an external zip file. The code should be posted **as text** in the question. If the code is too long, then you need to focus on the "Minimal" part of a MCVE by trimming it down to a sample that reproduces your problem. – dbush May 09 '19 at 13:36
  • 1
    The code in the linked ZIP file does not match the code in the question. In the ZIP file, `v_push_back` contains `if(v->e_type==V_INT){…`. In the question, it does not. Obviously, one should never expect to get a correct answer why code X is not working by asking about code Y. – Eric Postpischil May 09 '19 at 14:46

1 Answers1

2

Few problems I see,

  1. In order to get ith location of current vector type you need to multiply i with v->e_sz.

    void* v_at(vector_type v, iterator i)
    {
        .....
        return ((char*)v->e_array+i*v->e_sz); //return element    
    }
    
  2. You are allocating sizeof(void *) what you want is

     v->e_array = check_a(realloc(v->e_array, v->e_sz * v->cur_cap));
    
  3. Also as of now you are storing address as int but you need to store its value.

    void v_push_back(vector_type v, void* new_val){
         if(v->e_type==V_INT){
            //  (v->e_array+(v->no_e))=new_val;
            ((int*)v->e_array)[v->no_e]=*(int*)new_val;
                                        ^------storing its content
         }
    }
    

    Without any type checks, simple memcpy should work.

    void v_push_back(vector_type v, void* new_val){
        ....
        memcpy(
              v->e_array +(v->no_e)*v->e_sz,
              new_val,
              v->e_sz
              );
           //   *(char*)(v->e_array+v->no_e)=*(char*)new_val;
    
         (v->no_e)++;
     }
    
kiran Biradar
  • 12,700
  • 3
  • 19
  • 44