【问题标题】:C queue implementation using void* - good or bad practice?使用 void* 实现 C 队列 - 好习惯还是坏习惯?
【发布时间】:2013-07-17 21:43:14
【问题描述】:

我已经使用 void 指针在 C 中实现了一个基本的队列结构。程序如下:

  • 初始化结构 - 我设置了要存储在队列中的变量类型的大小
  • push - 我将指针传递给要存储的变量,然后队列为自己抓取一个副本
  • front - 结构返回一个 void* 给前面的元素。我可能只是抓住指针,或者 memcpy() 它有一个本地副本。

结构本身如下所示:

struct queue
{
    void* start;    //pointer to the beginning of queue
    void* end;      //-||- to the end
    size_t memsize; //size of allocated memory, in bytes
    size_t varsize; //size of a single variable, in bytes
    void* initial_pointer;      //position of the start pointer before pop() operations
};

start 和 end 只是指向当前分配的内存块中某个位置的 void 指针。如果我将元素推入队列,我会将结束指针增加varsize。如果我 pop(),我只需将结束指针也减少varsize

我不认为我应该在这里发布函数代码,它超过 100 行。

问题:这被认为是好的还是坏的做法?为什么(不)?

注意:我知道 C 中的队列还有很多其他选项。我只是询问这个队列的质量。

编辑:实现可在此处获得: http://89.70.149.19 /stuff/queue.txt(去掉空格)

【问题讨论】:

  • 使用 size_t 作为内存大小
  • 我认为使用void*编写通用代码很好
  • @RanEldan 谢谢,我会的。在这里更正了。
  • void* 肯定没问题。不过union 会更理想。
  • 经过下面的讨论后想到,您的意思是堆栈数据结构,而不是队列,不是吗?

标签: c pointers queue void


【解决方案1】:

您确实没有向我们展示足够的信息来确定您的实施。 void* 用户数据项很好,你不能在 C 中做很多其他事情。

但我强烈怀疑您有一个用于管理单个项目的内部列表元素类型,例如

struct list_item {
  struct list_item* next;
  void* data;
};

如果是这种情况并且您的 startend 指针指向此类元素,那么您绝对应该在 struct queue 声明中使用您的元素类型:

struct queue
{
    struct list_item* start;    //pointer to the beginning of queue
    struct list_item* end;      //-||- to the end
    size_t memsize; //size of allocated memory, in bytes
    size_t varsize; //size of a single variable, in bytes
    struct list_item* initial_pointer;      //position of the start pointer before pop() operations
};

为此,您甚至不必将struct list_item 的定义公开给struct queue 的用户。

【讨论】:

  • 我不确定你的意思。 start 和 end 只是指向当前分配的内存块中某个位置的 void 指针。如果我将元素推入队列,我会将结束指针增加 varsize。如果我 pop(),我只是将结束指针也减少 varsize。
  • @szczurcio,是一个非常规的队列实现,通常是我在这里描述的动态元素。您应该将您在评论中的描述添加到问题中,以供参考。然后我会删除这个答案,它对你没有多大帮助。
  • 好的,完成。但是我仍然不明白“常规”实现是什么意思。你能解释一下吗?
  • @szczurcio,“传统上”列表在 C 中实现为动态数据结构,由单个项目组成,如我的 list_item 通过引用链链接。乍一看,您将不得不重新调整您保留在幕后的元素数组的大小和起始位置。在某些情况下这可能是有利可图的,我不知道。我见过有人使用这样的数组来实现堆栈,但不是用于队列。
【解决方案2】:

如果不知道要存入队列的对象的类型和大小,使用void *也可以(其实C标准库也遵循同样的做法,见memcpy()和@987654323一些例子的@函数)。但是,最好使用size_t(或ssize_t,如果您需要签名数据类型)来指定存储在队列中的元素的大小。

【讨论】:

  • Ran Eldan 已经提到过,我已经更正了。好的,谢谢你的意见。我实际上认为这样做很直观,只是我看到有些人声称这很“丑陋”。
  • @szczurcio 问题是,如果您事先不知道类型,您将无法真正做任何其他事情。如果你这样做了,那么为了更好的类型安全,无论如何都不要使用void *
猜你喜欢
  • 2010-10-16
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多