简体   繁体   English

从void **数组返回数据

[英]Returning data from void** array

Suppose we have the following: 假设我们有以下内容:

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 that fp_t returns 0 if the two things compared are equal to each other (other return values for the function pointer are unimportant now). 进一步假设如果比较的两个事物彼此相等,则fp_t返回0(函数指针的其他返回值现在不重要)。 I'm also assuming, to make things easier, that the item in the second argument of find_item will always be in the array. 我还假设,为了使事情更容易, find_item的第二个参数中的find_item将始终在数组中。

I guess I'm having trouble understanding how void** works. 我想我无法理解void**工作原理。 In the get_data function, we're supplied as an argument a void* pointer to an array cell, which is a void* pointer to some data object. get_data函数中,我们作为参数提供了一个指向数组单元格的void*指针,该数组单元格是指向某个数据对象的void*指针。 So how do we get that data object? 那么我们如何获得该数据对象呢? I understand the user has to cast it for it to be useful, but I still don't know what I'm supposed to be returning. 我知道用户必须将其强制转换为有用,但我仍然不知道我应该返回什么。 I also know you can't dereference a void* , so doing something like return *item; 我也知道你不能取消引用空格void* ,所以做一些像return *item; (which in my mind seems like what we're trying to do- just get the void* pointer at the array cell), compiles with warnings/errors. (在我看来,这似乎是我们想要做的 - 只是在数组单元格中获取void*指针),编译警告/错误。

I guess delete_element carries the same type of confusion for me. 我想delete_element我带来同样的困惑。 We're supplied a void* pointer item , which points to a void* pointer array cell that points to the actual data. 我们提供了一个void*指针item ,它指向一个指向实际数据的void*指针数组单元格。 So we need to dereference the item somehow so that we can delete the array cell. 所以我们需要以某种方式取消引用该项目,以便我们可以删除该数组单元格。

Any ideas? 有任何想法吗?

It's easy to get confused by void * and void ** . 很容易被void *void **弄糊涂了。 A void * is a generic container for any pointer-to-object. void *是任何指向对象的指针的通用容器。 Any object pointer can be converted to void * and back again to the original value. 任何对象指针都可以转换为void *并再次返回原始值。 (Note that a void * is not guaranteed to be able to hold a function pointer). (注意, void *不保证能够保存函数指针)。 It doesn't really matter what type of objects these functions are handling. 这些函数处理的对象类型并不重要。 They are storing and retrieving objects (that just happen to have the type void * ). 它们存储和检索对象 (恰好有类型为void * )。

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

Your array member is simply a pointer to an array of objects. 您的array成员只是指向对象数组的指针。


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

I have no idea what this function is supposed to return, but the reason you're getting a warning from this is that you are removing a const qualifier. 我不知道这个函数应该返回什么,但是你收到警告的原因是你要删除一个const限定符。 You are turning a (pointer to) read-only object into a writable object. 您正在将(指向)只读对象转换为可写对象。 This is not allowed in C. To get away with this, you have to cast away the const qualifier. 在C中不允许这样做。为了避免这种情况,你必须抛弃const限定符。 ( return (void *)item; ). return (void *)item; )。

If item really is a pointer to an array cell (converted to void * ), then you have to cast it to the original type before you dereference it to retrieve the object. 如果item 确实是指向数组单元格的指针(转换为void * ),那么在取消引用它以检索对象之前,必须将其强制转换为原始类型。 ( return *(void **)item; ). return *(void **)item; )。 But I really have no idea 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're supposed to go through the array of objects until you find one that compares equal to item , remove it from the array by moving the following objects to fill that slot, and then adjust the length . 你应该去通过array的对象,直到找到一个比较等于item ,通过移动下列对象,以填补该插槽从数组中删除它,然后调整length The only thing you have to dereference is the array pointer, not the stored objects. 您必须取消引用的唯一内容是array指针,而不是存储的对象。


 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 probably return NULL if item is not found. 如果找不到item此函数应该返回NULL Just return NULL; return NULL; right before the functions closing brace. 就在关闭括号的功能之前。

int* is a pointer to int. int*是指向int的指针。 Given int* x pointing to valid memory for each of the following, *x and x[0] references the memory x points to; 给定int* x指向以下每个有效内存, *xx[0]引用内存x指向; x+1 points to the location sizeof(int) bytes after x, *(x+1) or x[1] references that location; x+1指向x, *(x+1)x[1]之后的位置sizeof(int)字节引用该位置; x+2 points to the location sizeof(int)*2 bytes after x, and so on. x+2指向位置sizeof(int)*2 x之后的sizeof(int)*2个字节,依此类推。

void is not type of object; void不是对象的类型; so void* is a pointer to memory but not a pointer to something. 所以void*是指向内存的指针,但不是指向某个东西的指针。 Given void* y , *y , y[0] , y+1 , *(y+1) , etc simply don't make sense. 给定void* y*yy[0]y+1*(y+1)等等根本没有意义。

void* is a type of an object--it is a pointer to memory. void* 一种对象 - 它是一个指向内存的指针。 Given void** z pointing to valid memory for each of the following, *z and z[0] references the memory z points to; 给定void** z指向以下每一个的有效存储器, *zz[0]引用存储器z指向; z+1 points to the location sizeof(void*) bytes after z, and so on. z+1指向z+1的位置sizeof(void*)字节,依此类推。

If it helps, pretend "void*" is spelled "pointer" (as if you are using typedef void* pointer ), and is on par with "int". 如果它有帮助,假装“void *”拼写为“指针”(就好像你使用的是typedef void* pointer ),并且与“int”相同。 So, if I have int q and pointer p, I can't do *q because q isn't a pointer to something, nor can I do *p because p isn't a pointer to something (strictly this is true). 所以,如果我有int q和指针p,我不能做*q因为q不是指向某个东西的指针,也不能做*p因为p不是指针的东西(严格来说这是真的)。 But you can assign int's to other int's, and assign pointer's to other pointers; 但是你可以将int分配给其他int,并将指针指定给其他指针; and you can allocate memory for int* just as you can allocate it for pointer* , and dereference objects of type pointer* just as you can with int*. 您可以为int*分配内存,就像为pointer*分配内存一样,并且可以像使用int *一样取消引用类型为pointer*对象。

That's enough to answer your question, but to do what you want to do generally depends on a few implementation details. 这足以回答你的问题,但做你想做的事情一般取决于一些实现细节。 If you're going to store memory as arrays of void* 's (aka, void** 's or "pointer*'s"), you will need to either require your user pass you a create function, or just allocate each element's memory themselves (or just handle it themselves, if you want to allow them to point to non-heap objects; it really depends on what you want to do; if you let them have items pointing to non-heap objects, though, you probably don't want to delete it). 如果你要将内存存储为void*的数组(aka, void**或“pointer * s”),你需要要求你的用户传递一个create函数,或者只是分配每个元素的内存本身(或者只是自己处理它,如果你想让它们指向非堆对象;它实际上取决于你想要做什么;如果你让它们有指向非堆对象的项目,那么,你可能不想删除它)。 Your code could delete the items easily enough. 您的代码可以轻松删除项目。 How to remove items from this set is another implementation detail--depends on what you want to do. 如何从该集中删除项目是另一个实现细节 - 取决于您想要做什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM