【问题标题】:What is the best way to store integers with void pointers in C?在 C 中使用 void 指针存储整数的最佳方法是什么?
【发布时间】:2020-07-23 00:55:04
【问题描述】:

您好,我正在尝试在 c 中学习和构建数据结构,并且我想将整数逐步存储在堆栈中。 我的结构是这样的:

typedef struct STACK_NODE_s *STACK_NODE;
typedef struct STACK_NODE_s{
    STACK_NODE forward;
    void *storage;
} STACK_NODE_t;

typedef struct L_STACK_s{
    STACK_NODE top;
} L_STACK_t, *L_STACK;

在 while 循环中,我想以整数形式读取和存储我的字符。

//assume that str is an proper string
//assume that we have a linked stack called LS
int i=0;
int temp;
while(str[i]!='\0'){
    tmp=str[i]-'0';
    push(LS,(void *)&tmp);
}

我知道这不会正常工作,因为我们一遍又一遍地存储同一个变量的地址。 我是否需要分配一个辅助数组才能将它们一一存储,还是有更好的方法来做到这一点?

【问题讨论】:

  • 您的堆栈使用void* 存储数据的原因是什么?
  • 用于类通用库的实现。
  • 在这种情况下,您将不得不使用malloc(或以某种比堆栈更有效的方式动态分配数据)并记住在销毁堆栈时free所有元素
  • @UnholySheep 嗯,我已经习惯了这些地址,但它们仍然让我有些困惑。我会尝试这种方法谢谢。

标签: c data-structures linked-list stack void-pointers


【解决方案1】:

答案必须针对您的问题的两个不同方面: 如何组织一些项目的集合,以及从哪里获取内存来做到这一点。

首码sn -p / 链表格式

第一个代码 sn-p 就是这样。 它设置了一个linked list,它有它的优点和缺点,但是如果你事先不知道物品的数量,如果你希望能够在中间的某处快速移除或插入物品,它会非常有用列表,如果您不介意在列表中查找某个条目会花费您O(N) effort

对于类通用库的实现...

...void* 与 ANSI C 一样好。 例如,在 C++ 中,您可以创建一个模板,使存储在列表中的类型保持打开状态(或者更好的是,您可以直接重用类 forward_list<int> 中众所周知的 STL 实现)。 可悲的是,ANSI C 没有可比的东西。 一种解决方案是您选择的解决方案,创建int 对象并将它们的地址挂钩到您的void* 列表中。 泛型库实现的另一种解决方案是使用类型的预编译器宏,并在包含泛型实现的头文件上方定义此宏。这试图类似于干净的 C++ 解决方案,但使用预编译器它不是类型安全的,因此这种方法远非美观,并且存在一些风险。

第二个代码sn -p / 内存分配

使用void* 而不是int(或任何非指针类型)创建列表需要您在列表旁边分配更多内存。 即,您不仅要分配每个列表项(= STACK_NODE_t 类型的变量),还要分配实际的条目值(例如,*(int*)(LS->storage))。

这意味着您必须以某种超出堆栈的其他方式分配/取消分配数据。 在大多数系统上,您可以为此使用malloc/free,并且您只需考虑可用于malloc 的堆大小以及取消/分配所需的时间。 如果列表要实现实时要求或在嵌入式系统上,您可能没有malloc,或者您可能不被允许使用它。 然后你必须为你的列表分配和实现你自己的堆(=storage 项目的内存池)。 如何实现这样一个具有所需属性的内存池是一个单独的问题,它将带我们到这里很远。

在任何情况下,您都不能使用指向堆栈变量的指针(就像函数内部的局部变量),因为一旦函数退出,该变量“后面”的内存将不会为此目的而保留,并且内存可能同时用于不同的东西。 然而,这显然是第二个代码 sn-p 所做的。 正如你自己注意到的那样,走这条路……

我们一遍又一遍地存储同一个变量的地址。

为同一列表的另一个条目重用内存位置是上述风险的极端情况。

【讨论】:

  • 感谢您非常详细的解释和极大的帮助。得益于此,我学到了很多关于 malloc 和未使用内存管理的新知识。
【解决方案2】:

我像预期的那样使用辅助数组解决了这个问题。如果有人想出更好的解决方案,那就太受欢迎了。

【讨论】:

  • 为什么不把str[i]的地址直接转成整数再把它的地址压入栈呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2019-02-03
相关资源
最近更新 更多