Returning data from a void array **

Suppose we have:

struct container
{
   void** array;
   function_pointer_typedef fp_t;
   int length;
};

void* get_data(const void* item){
   return item; //unsure. also produced warning.
}

void delete_element(container* c, void* item)
{
   /* 1. delete the array element pointed at by "item"
      2. reposition remaining array elements
   */
}

void* find_item(container* c, void* item)
{
   int i;
   for(i = 0; i < c->length; i++){
      if(c->fp_t(item, c->array[i]) == 0){
         return c->array[i];
      }
   }
}

      

Further, suppose it fp_t

returns 0 if the two things compare with each other (other return values ​​for the function pointer are irrelevant right now). I also assume, to keep things simple, that the element in the second argument find_item

will always be in the array.

I think it's hard for me to understand how it works void**

. In the function, get_data

we provide the argument a to a void*

pointer to an array cell, which is a pointer void*

to some data object. So how do we get this data object? I understand that the user has to throw it for it to be useful, but I still don't know what I should be returning. I also know that you cannot enact void*

, so doing something like return *item;

(which, in my opinion, is similar to what we are trying to do - just get a pointer void*

in an array cell) compiles with a warning / error.

I guess delete_element

carries the same confusion for me. We are provided with a pointer void*

item

that points to a cell in the array of pointers void*

that points to the actual data. Therefore, we need to somehow split the element in such a way that we can delete the array cell.

Any ideas?

+3


source to share


2 answers


It is easy to get confused void *

and void **

. A void *

is a general container for any pointer to an object. Any object pointer can be converted to void *

and returned to the original value. (Note that a void *

cannot contain a function pointer). It doesn't really matter what type of object these functions are. They store and retrieve objects (which just have a type void *

).

struct container
{
   void** array;
   function_pointer_typedef fp_t;
   int length;
};

      

Your member array

is just a pointer to an array of objects.


void* get_data(const void* item){
   return item; //unsure. also produced warning.
}

      

I don't know how this function is supposed to return, but the reason you are getting a warning from this is because you are removing the classifier const

. You are turning a read-only object (pointer to) into a writable object. This is not allowed in C. To avoid this, you must drop the qualifier const

. ( return (void *)item;

).

If item

indeed is a pointer to an array cell (converted to void *

), then you must give it to the original type before you can look up to retrieve the object. ( return *(void **)item;

). But I really don't know what this function is supposed to do. Ask your teacher.




void delete_element(container* c, void* item)
{
   /* 1. delete the array element pointed at by "item"
      2. reposition remaining array elements
   */
}

      

You have to traverse the objects array

until you find the one that is compared to item

, remove it from the array by moving the following objects to fill that slot, and then adjust.The length

only thing you have to dereference is the pointer array

, not the stored objects.


void* find_item(container* c, void* item)
{
   int i;
   for(i = 0; i < c->length; i++){
      if(c->fp_t(item, c->array[i]) == 0){
         return c->array[i];
      }
   }
}

      

This function should return NULL

if item

not found. Just return NULL;

right before the function's closing function.

+4


source


int*

is a pointer to int. Given that it int* x

points to valid memory for each of the following, *x

and x[0]

refers to the memory x it points to; x+1

indicates the location of sizeof(int)

bytes after x, *(x+1)

or x[1]

references to that location; x+2

indicates the location of the sizeof(int)*2

bytes after x, etc.

void

is not an object type; therefore it void*

is a pointer to memory, not a pointer to something. Given the void* y

, *y

, y[0]

, y+1

, *(y+1)

and so on, simply do not make sense.

void*

is the type of object - it is a pointer to memory. Given void** z

, pointing to valid memory for each of the following, *z

and z[0]

references pointed to by z; z+1

indicates the location of the sizeof(void*)

bytes after z, etc.



If that helps, pretend that "void *" is being written "pointer" (as if you were using it typedef void* pointer

) and is level with "int". So if I have an int q and a pointer p, I cannot do *q

because q is not a pointer to something, and I cannot do *p

because p is not a pointer to something (strictly this is true). But you can assign int to other int and assign a pointer to other pointers; and you can allocate memory for int*

just as you can allocate it for pointer*

, and scavenge for pointer objects of type * just as you can with int *.

This is enough to answer your question, but doing what you want to do usually depends on a few implementation details. If you're going to store memory as arrays void*

(aka, void**

or "pointer * 's), you need to either require your user to pass the create function to you, or just allocate each element's memory (or just handle it yourself if you want to allow them to specify non-heap objects, it really depends on what you want to do, if you let them have elements pointing to non-heap objects, although probably t want to delete it). Your code can easily remove elements. How to remove elements from this set - it's another implementation detail - depends on what you want to do.

+1


source







All Articles