2013-03-17 55 views
0

我正在制作我的图书馆,当我想到了解指针语法时,我只是感到困惑,在网络上搜索并且变得更加困惑。如何使用C中的指针创建池?

基本上我想打一个游泳池,这里是我真正想做的事:

context

以下几点必须遵守:

  • 当我添加对象到池中,当前数组指向对象的指针是 添加到一个新的指针数组+1(包含新对象)。
  • 新阵列由我的foo结构的“对象”指向。
  • 旧阵列正在释放。
  • 当我打电话的清理功能,在池中的所有对象都 free'd

我应该如何定义我的结构?

typedef struct { 
    int n; 
    (???)objects 
} foo; 
foo *the_pool; 

这里的代码来管理我的池:

void myc_pool_init() 
{ 
    the_pool = (???)malloc(sizeof(???)); 
    the_pool->n = 0; 
    the_pool->objects = NULL; 
} 

void myc_push_in_pool (void* object) 
{ 
    if (object != NULL) { 
     int i; 
     (???)new_pointers; 

     the_pool->n++; 
     new_pointers = (???)malloc(sizeof(???)*the_pool->n); 

     for (i = 0; i < the_pool->n - 1; ++i) { 
      new_pointers[i] = (the_pool->objects)[i]; // that doesn't work (as I'm not sure how to handle it) 
     } 
     new_array[i] = object; 

     free(the_pool->objects); 
     the_pool->objects = new_array; // that must be wrong 
    } 
} 

void myc_pool_cleanup() 
{ 
    int i; 
    for (i = 0; i < the_pool->n; ++i) 
     free((the_pool->objects)[i]); // as in myc_push_in_pool, it doesn't work 
    free(the_pool->objects); 
    free(the_pool); 
} 

注:对象的类型添加到池中,在事先不知道,所以我应该处理为void 所有指针任何反馈都会非常受欢迎。

+0

如果C有这种类型的泛型编程,你不觉得[qsort](http://pubs.opengroup.org/onlinepubs/009695399/functions/qsort.html)将使用该函数代替回调函数,并且宽度参数? – Sebivor 2013-03-17 14:58:25

+0

@GrijeshChauhan这本书在第一页说:“只有面向对象允许项目之间的代码重用”。彻底废话!这位作者很困惑。如果没有面向对象的代码重用是不可能的,请在Haskell中解释抽象。 – Sebivor 2013-03-17 15:31:11

+1

看看Ted Jensen的[“C中数组和指针的教程”](http://home.earthlink.net/~momotuk/pointers.pdf),也许可以回顾一下Steve Summit的[“Introductory C programming”] (http://www.eskimo.com/~scs/cclass/cclass.html)。日期,但在问这里之前应该先阅读...... – vonbrand 2013-03-17 16:54:23

回答

3

直接回答你的问题是:使用void *。这种类型非常强大,因为它允许您将任何类型的指针放入池中。但是,从您的游泳池中检索void *指针时,您需要做正确的强制转换。

你的结构是这样的

typedef struct { 
    int n; 
    (void **)objects 
} foo; 
foo *the_pool; 

如,指针数组。

你的malloc:

new_pointers = (void **)malloc(sizeof(void *)*the_pool->n); 

这里有一个性能问题。您可以简单地分配一个固定大小的数组,并且只在元素数量超过预定义的加载因子(=已用数量/最大大小)时才重新分配数组。您的游泳池,你可以只使用reallochttp://www.cplusplus.com/reference/cstdlib/realloc/

the_pool->objects = (void **)realloc(the_pool->objects, the_pool->n* sizeof(void*)); 

ReAlloc如果试图增加当前分配的区域,而不需要复制的一切。只有当函数不能连续增加分配区域时,它才会分配一个新区域并复制所有内容。

+4

不需要从malloc转换返回值。 – 2013-03-17 16:35:45

+0

我真的很感谢你的回答,现在我明白了指针的用法。并感谢realloc提示。 – user544262772 2013-03-17 16:55:54

0

首先,你已经回答了你的“foo.objects的类型是什么?“问题:void *objects;,malloc的已经返回了void *你的结构需要存储size_t item_size;,太n应该也可能是size_t

typedef struct { 
    size_t item_count; 
    size_t item_size; 
    void *objects; 
} foo; 
foo *the_pool; 

可以使用一个土生土长的循环,但我。考虑的memcpy是你的旧项目复制到新的空间更方便的方式,和它的新项目的新空间。

解引用void *是违反约束,因为是在一个void *指针运算,所以new_pointers会需要是一个不同的类型。您需要一个指向正确大小的对象的类型。你可以使用一个数组权数的unsigned char,就像这样:

// new_pointers is a pointer to array of the_pool->item_size unsigned chars. 
unsigned char (*new_pointers)[the_pool->item_size] = malloc(the_pool->item_count * sizeof *new_pointers); 

// copy the old items 
memcpy(new_pointers, the_pool->objects, the_pool->item_count * sizeof *new_pointers); 

// copy the new items 
memcpy(new_pointers + the_pool->item_count, object, sizeof *new_pointers); 

记住,免费()通过的malloc(返回指针),并且应该有一个一对一一个对应关系:每个malloc()都应该是free()d。看看你是如何malloc:new_pointers = malloc(sizeof(???)*the_pool->n); ...什么让你觉得你需要一个循环(在myc_pool_cleanup)来释放每个项目,当你可以在一个犯规突击全部释放他们?

可能使用realloc,但你似乎在完美地处理myc_push_in_pool *中的malloc/memcpy/free *。编写realloc代码时,很多人往往会搞砸。