功能顶层堆栈实现在C中

时间:2016-07-11 07:06:55

标签: c generics data-structures stack

我正在C中实现一个通用堆栈用于学习目的。这是它的流行功能:

void* StackPop(Stack *s) {
    assert(s != NULL);
    assert(s->logicalLen > 0); // there must be at least on element
    void *object = (char*) s->elems + (s->logicalLen--) * s->elemSize; // decrement logical length
                                                                       // on the fly
    return object;
}

在这种情况下(StackPop)我很清楚我必须将顶部对象的所有权转移给调用者。因此返回一个通用指针很好,因为调用者想要决定如何处理该对象。 另一方面,我想写一个StackTop()函数来返回顶部元素。这对我来说是如此不确定:我知道两个函数应该非常相似,不同之处在于我不应该减小堆栈的大小或返回指针,因为我不希望客户端修改它。如何仅传递顶级元素的副本呢?接受一个通用指针作为参数我唯一的选择并深入复制到该地址?

void StackPop(void *target) {
    // make a deep copy into target address with memcopy or whatever?
}

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

  

我知道这两个功能应该非常相似......

谁说的?

您正在设计堆栈,因此您可以自由定义使用堆栈的所有规则。例如,您允许跳过对NULL指针的所有检查,只需在文档中写入使用NULL指针调用函数xxx会导致未定义的行为。最后,它取决于你想要的堆栈 - 高性能,安全使用,易于使用等。

这同样适用于StackPopStackTop函数。你可以自由设定规则。

对我来说,StackPop似乎在逻辑上是错误的。通过递减logicalLen返回指向逻辑上已释放的内存区域的指针并不是我所期望的。但是你可以在文档中写下StackPop返回的指针在下一个StackPush时变为无效。 (在C ++中,一些容器对迭代器/指针有这样的限制。)

同样适用于StackTop - 您只需返回指向顶部元素的指针,并声明它仅在下一个StackPop之前有效。

这是你的设计,你的规则。

我宁愿这样做:

int push(stack* s, void* o)
{
    // memcpy contents of o to next free location
    // increment number of elements held
}

int top(stack* s, void* o)
{
    // memcpy top element to o
}

int pop(stack* s)
{
    // decrement number of elements held
}

在所有三种情况下,int用于返回错误值。

为了提高性能,您可以提供一项功能,例如: ptop返回指向顶部元素的指针(仅对下一个pop有效)。

关于deep copy

您无法在通用堆栈中执行深层复制。如果用户在堆栈中放入有指针的内容,则用户必须自己处理。