473,320 Members | 1,977 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Implementation of a Vector of structures in C

Hi,

I created a structure Vector and implement some functions to make the new defined type (vector) dynamically allocated and resized (inspired from the C++ implementation of the dynamic arrays : vector). I need to assign a structure to every vector element but I am not sure that I am doing it right:

here is the structure that I ve defined:

************************************************** **********
Expand|Select|Wrap|Line Numbers
  1. typedef struct 
  2. {
  3.     void** mem; // to make this parametrizable I want the void* to point to a Structure (referenced with * a pointer)
  4.     unsigned long     elems;
  5.     unsigned long     elemsize; //element size
  6.     unsigned long     capelems; //capacity of the vector.Returns the size of the storage space
  7.                               //currently allocated for the vector, expressed in terms of elements
  8.     unsigned long     reserve;  
  9. } Vector;
  10. ************************************************************
  11.  
  12. the source file is given below:
  13. ************************************************************
  14.  
  15. //action of setting a new vector
  16. Vector* newVector(void *data, unsigned long elemsize)
  17. {
  18.     Vector* pvec = (Vector*)malloc(sizeof(Vector)); //memory space set
  19.     if( pvec == NULL )
  20.      FatalError("Malloc failed.\n");
  21.      memset(pvec, 0, sizeof(Vector));
  22.  
  23.     pvec->reserve = 1024;
  24.     pvec->capelems = pvec->reserve;
  25.     pvec->elemsize = elemsize;
  26.     pvec->elems = 0;
  27.  
  28.     pvec->mem = (data)malloc(pvec->capelems * pvec->elemsize); //pvec->elemsize is the sizeof(data)
  29.      if(  pvec->mem == NULL )
  30.        FatalError("Vector Malloc failed.\n");
  31.        memset(pvec->mem, 0, sizeof(pvec->capelems * pvec->elemsize));
  32.     return pvec;
  33. }
  34.  
  35. //action of deleting a vector
  36. void deleteVector(Vector* pvec)
  37. {
  38.     free(pvec->mem);
  39.     free(pvec);
  40. }
  41.  
  42. //action of extending a vector size
  43. void resizeVector((Vector* pvec, void* data, unsigned long capacity)
  44. {
  45.     pvec->capelems = capacity;
  46.     void* mem = (data)malloc((pvec->capelems + pvec->reserve) * pvec->elemsize);
  47.     memcpy(mem, pvec->mem, pvec->elems * pvec->elemsize); //copy characters from memory
  48.     free(pvec->mem);
  49.     pvec->mem = mem;
  50.     pvec->capelems += pvec->reserve;
  51. }
  52.  
  53. //action of pushing back an element to a vector
  54. //Adds a new element at the end of the vector, after its current
  55. //last element.The content of val is copied (or moved) to the new element
  56. void push_backVector(Vector* pvec, void* data, unsigned long elemsize)
  57. {
  58.     assert(elemsize == pvec->elemsize); //check certain conditions at run time
  59.     if (pvec->elems == pvec->capelems) 
  60.     {
  61.         resizeVector(pvec, pvec->capelems);
  62.     }
  63.     memcpy(pvec->mem + (pvec->elems * pvec->elemsize), data, pvec->elemsize); 
  64.     pvec->elems++;    
  65. }
  66.  
  67. //action of  returning the vector length
  68. unsigned long lengthVector(Vector* pvec)
  69. {
  70.     return pvec->elems;
  71. }
  72.  
  73. //action of returning a value of index "index" of a vector "vector"
  74. void* getVectorElement(Vector* pvec, unsigned long i_index)
  75. {
  76.     assert(i_index < pvec->elems); //if evaluated to False, an error message is returned and program aborted
  77.     return (void*)(pvec->mem + (i_index * pvec->elemsize)); 
  78. }
  79.  
  80. //action of copying an item of a vector
  81. void copyVectorItem(Vector* pvec, void* destination, unsigned long i_index)
  82. {
  83.     memcpy(destination, getVectorElement(pvec, i_index), pvec->elemsize);
  84. }
************************************************** **********

I believe I have serious problems with pointers, values and dereferencing a pointer.

Can anyone give me a hand please.

Regards

N.Wilson
Apr 14 '14 #1

✓ answered by weaknessforcats

Expand|Select|Wrap|Line Numbers
  1. elemsize = sizeof (data);
On this issue, your vector is an array of data.

As an array, the vector sees only the address of element 0. Therefore, sizeof(data) is just the size of a pointer on your system. Since all pointers are the same size, your array elements are always just the size of an address.

However, here:
Expand|Select|Wrap|Line Numbers
  1.  data = malloc(pvec->capelems * pvec->elemsize); 
won't work because you don't know the size of the struct pointed at. You need something like:

Expand|Select|Wrap|Line Numbers
  1.  data = malloc(pvec->capelems * sizeof(the struct pointed at)); 
otherwise you get an array of elements as big as pointers to structs rather than an array of structs.

Therefore, you need to know the size of the struct.

Therefore, you need a discriminator you can use to do a typecast to the correct type in the malloc statement to get an array of the right size for the type.



Therefore, you define a discriminator.

Therefore, you define the values of the discriminator:
Expand|Select|Wrap|Line Numbers
  1. int discrim;  //0 means char, 1 means int, etc...
Therefore, you will be able to support a limited number of types. (This is actually the main reason for templates in C++).

Expand|Select|Wrap|Line Numbers
  1.      switch (discrim)
  2.       {
  3.         case 1:
  4.              data = malloc(pvec->capelems * sizeof(char));
  5.              break;
  6.         case 2:
  7.               data = malloc(pvec->capelems *sizeof(int));    
  8.               break;
  9.         etc...
  10.  
  11.  
When you get this working, post again and we'll work on assignment issues.

7 2177
weaknessforcats
9,208 Expert Mod 8TB
There are several problems here.

First, there is no info on what the struct is that the vector points to. That means there is no way to free the vector without running the risk of leaking because you cannot free the data struct.

Second, you cannot assign since all you can do is assign the address of the data struct. You cannot have a data struct address in two paces.

The only way to do this in C is to use a discriminator in the vector struct that identifies the type of struct pointed at.

You might check out http://msdn.microsoft.com/en-us/library/dd338762.aspx

I assume this is a school exercise since you would use C++ vector in real life coding.
Apr 15 '14 #2
would it be correct to do this then:

Expand|Select|Wrap|Line Numbers
  1. //action of setting a new vector
  2. Vector* newVector(void *data, unsigned long elemsize)
  3. {
  4.     Vector* pvec = (Vector*)malloc(sizeof(Vector)); //memory space set
  5.     if( pvec == NULL )
  6.      FatalError("Malloc failed.\n");
  7.      memset(pvec, 0, sizeof(Vector));
  8.  
  9.     pvec->reserve = 1024;
  10.     pvec->capelems = pvec->reserve;
  11.     elemsize = sizeof (data);
  12.     pvec->elemsize = elemsize;
  13.     pvec->elems = 0;
  14.     data = malloc(pvec->capelems * pvec->elemsize); //pvec->elemsize is the sizeof(data);
  15.     if(  data  == NULL )
  16.        FatalError("Vector Malloc failed.\n");
  17.        memset(data, 0, sizeof(pvec->capelems * pvec->elemsize));
  18.  
  19.     pvec->mem = data;
  20.  
  21.     return pvec;
  22. }
  23.  
thx
Apr 15 '14 #3
weaknessforcats
9,208 Expert Mod 8TB
Expand|Select|Wrap|Line Numbers
  1. elemsize = sizeof (data);
  2. pvec->elemsize = elemsize;
  3.  
This code will always give the same answer: The size of a pointer. data is a void*.

Also, a void* is totally useless unless you know the type it really points at. To use it you need to typecast the void* to the correct type. A discriminator can carry a code that tells the function what typecast to use. Usually, this is a switch statement inside the function.

You cannot use mem... functions. The struct pointed at may have elements on the heap you need to free before freeing the pointer to the struct. This implies you need to know how to free the struct object from inside your vector. Further, you cannot free a pointer unless you are certain that you are freeing the only pointer to that struct object. This may mean you have to implement managed (smart) pointers).

Then there are the assignment issues. Assignment means making a copy. That means deleting the current content and replacing it with a copy of the new content. Again, no mem... function will work because a copy may contain pointers and you do not want to copy the pointer (shallow copy) because cleanup will delete the pointer and that will crash the object for other pointers to the same object. Instead, you need to make a copy of the object pointed at. You cannot assign an object to itself because the assignment will delete the current content first thereby torching the very data to be used to make a copy. You may want to research assignment rules.
Apr 15 '14 #4
lots of work to do then,
If you don't mind I prefer to go step by step (I am new to pointers and structures that 's why I have some issues)
I used the void pointer to be able to change the vector's pointed elements. For instance here I try to make a new vector called NetRouters where every element of NetRouters is a pointer to a structure Switch. In the main program I call the newVector function as follows:

"Also, a void* is totally useless unless you know the type it really points at. To use it you need to typecast the void* to the correct type. A discriminator can carry a code that tells the function what typecast to use. Usually, this is a switch statement inside the function."


Expand|Select|Wrap|Line Numbers
  1. Vector* NetRouters = newVector(aSwitch, sizeof(Switch*));
can this work ?

Should I omit these lines and mention the size of my structure as the second newVector function' arguments

Expand|Select|Wrap|Line Numbers
  1. elemsize = sizeof (data);
  2.     pvec->elemsize = elemsize;
I think I should first fix this befor moving to the other issues (to me it seems hard to understand what you told me about allocate/free memory pointed )

Thks
Apr 15 '14 #5
weaknessforcats
9,208 Expert Mod 8TB
Expand|Select|Wrap|Line Numbers
  1. elemsize = sizeof (data);
On this issue, your vector is an array of data.

As an array, the vector sees only the address of element 0. Therefore, sizeof(data) is just the size of a pointer on your system. Since all pointers are the same size, your array elements are always just the size of an address.

However, here:
Expand|Select|Wrap|Line Numbers
  1.  data = malloc(pvec->capelems * pvec->elemsize); 
won't work because you don't know the size of the struct pointed at. You need something like:

Expand|Select|Wrap|Line Numbers
  1.  data = malloc(pvec->capelems * sizeof(the struct pointed at)); 
otherwise you get an array of elements as big as pointers to structs rather than an array of structs.

Therefore, you need to know the size of the struct.

Therefore, you need a discriminator you can use to do a typecast to the correct type in the malloc statement to get an array of the right size for the type.



Therefore, you define a discriminator.

Therefore, you define the values of the discriminator:
Expand|Select|Wrap|Line Numbers
  1. int discrim;  //0 means char, 1 means int, etc...
Therefore, you will be able to support a limited number of types. (This is actually the main reason for templates in C++).

Expand|Select|Wrap|Line Numbers
  1.      switch (discrim)
  2.       {
  3.         case 1:
  4.              data = malloc(pvec->capelems * sizeof(char));
  5.              break;
  6.         case 2:
  7.               data = malloc(pvec->capelems *sizeof(int));    
  8.               break;
  9.         etc...
  10.  
  11.  
When you get this working, post again and we'll work on assignment issues.
Apr 15 '14 #6
Hi ,

I changed my code as follows:
Expand|Select|Wrap|Line Numbers
  1. //action of setting a new vector
  2. Vector* newVector(char data)
  3. {
  4.     //Switch* aSwitch;
  5.     //Channel* aChannel;
  6.  
  7.     Vector* pvec = (Vector*)malloc(sizeof(Vector)); //memory space set
  8.     if( pvec == NULL )
  9.      FatalError("Malloc failed.\n");
  10.      memset(pvec, 0, sizeof(Vector));
  11.  
  12.     pvec->reserve = 1024;
  13.     pvec->capelems = pvec->reserve;
  14.     pvec->elems = 0;
  15.  
  16.     switch (data)
  17.     {
  18.         case 'S':
  19.         {        
  20.             pvec->elemsize =  (unsigned long) sizeof(Switch);
  21.  
  22.             pvec->mem = (Switch *) malloc( sizeof(Switch) * pvec->capelems );
  23.  
  24.             if(  pvec->mem  == NULL )
  25.             FatalError("Vector Malloc failed.\n");
  26.             memset(pvec->mem, 0, sizeof(pvec->capelems * pvec->elemsize));    
  27.  
  28.             printf("allocation of vector of switches is done !\n");
  29.  
  30.         break;
  31.         }
  32.  
  33.         case 'C':
  34.         {
  35.  
  36.             pvec->elemsize = sizeof(Channel);
  37.  
  38.             pvec->mem  =  (Channel *) malloc(pvec->capelems * sizeof(Channel)); //pvec->elemsize is the sizeof(data);
  39.  
  40.             if(  pvec->mem  == NULL )
  41.             FatalError("Vector Malloc failed.\n");
  42.             memset(pvec->mem, 0, sizeof(pvec->capelems * pvec->elemsize));    
  43.  
  44.             printf("allocation of vector of channels is done !\n");    
  45.  
  46.         break;            
  47.         }
  48.  
  49.         default:
  50.         break;
  51.     }   
  52.  
  53.     return pvec;
  54. }
  55.  
Until now I don't have any faults (segmentation ) But I still need run the whole project to see what can this give.

Is it the way that you advised me to do ?

Best Regrads,

N. Wilson
Apr 21 '14 #7
weaknessforcats
9,208 Expert Mod 8TB
Yes it is.

However, when you memset to 0 the 0 is a valid value for an unsigned long and a char. I suggest you pick a value that you document as not being valid for data. Maybe 0xFFFFFFFF for the unsigned long and 0xF for the char.

As an improvement, maybe after you get things working, is to remove all displays from your code and replace them with error codes that are returned. You should avoid missing your screen manager with your vector. Microsoft often does not return errors but when one occurs, the error is written to a place where a GetLastError() function can retrieve it.
Apr 22 '14 #8

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: wtnt | last post by:
Hello, I've been using the STL libraries for some time, but still don't know the ins and outs of its implementation. Could this be because there's more than 1 implementation? Does anyone know of...
6
by: Jonathan | last post by:
I am hoping that someone more experienced than myself can point me towards what might be the fastest data lookup method to use for storing ip addresses. My situation is that I will need to maintain...
4
by: Nomak | last post by:
Hello, With this code: $ cat -n ifs.cc 1 #include <vector> 2 #include <iostream> 3 4 using std::vector; 5 using std::cin;
8
by: Hamish | last post by:
I havea program which on execution gives unpredictable behaviour (it shouldn't). In trying to track down the problem, I'm wondering if there is a difference between these two ways of filling a...
8
by: Joseph Turian | last post by:
Fellow hackers, Is it possible to shrink the capacity of a vector? i.e. Without new'ing and delete'ing a vector, can one return its memory to the heap? Here's what I get under the g++...
11
by: koperenkogel | last post by:
Dear cpp-ians, I am working with a vector of structures. vector <meta_segment> meta_segm (2421500); and the structure look like: struct meta_segment { float id; float num;
8
by: Generic Usenet Account | last post by:
I have a need for a set operation (actually multi-set operation) on sorted structures that is not in the STL library. I call it the set_retain operation. It's kinda similar to the...
2
by: jeff_j_dunlap | last post by:
I recently began using STL containers, mainly to store pointers to structures using a vector: std::vector <dataStruc*vdata; Next, I fill the container within a loop: vdata.push_back(new...
8
by: Bryan | last post by:
Hello all. I'm fairly new to c++. I've written several programs using std::vectors, and they've always worked just fine. Until today. The following is a snippet of my code (sorry, can't...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.