StackTop函数的这两种不同实现之间有什么区别?

StackTop函数的这两种不同实现之间有什么区别?,c,stack,structure,C,Stack,Structure,我正在学习一门关于数据结构的课程,目前我被困在堆栈中。在StackTop函数的实现中(复制或“在某种意义上返回”堆栈中的顶部元素,而不影响堆栈)。下面的代码是它的实现,很清楚 void StackTop(StackEntry *pe, Stack *ps){ *pe=ps->entry[ps->top-1]; } 但是,只要我们想给用户堆栈中top元素的值,我们就不能这样做函数吗?如果是这样,那么这两种实现之间有什么区别 StackEntry StackTop(Stack

我正在学习一门关于数据结构的课程,目前我被困在堆栈中。在
StackTop
函数的实现中(复制或“在某种意义上返回”堆栈中的顶部元素,而不影响堆栈)。下面的代码是它的实现,很清楚

void StackTop(StackEntry *pe, Stack *ps){
    *pe=ps->entry[ps->top-1];
}
但是,只要我们想给用户堆栈中top元素的值,我们就不能这样做函数吗?如果是这样,那么这两种实现之间有什么区别

StackEntry StackTop(Stack *ps){
    return ps->entry[ps->top-1];
}

请记住,
StackEntry
是一种用户定义的数据类型。

任何一种都可以使用。主要区别在于完成的副本数量

在第一种情况下,结果值通过指针解引用直接写入目标变量。在第二种情况下,值(在大多数实现中)放在堆栈上,然后复制到接收返回值的变量,假设已分配返回值


对于返回值的情况,如果返回结构,编译器可能不会将返回值复制到堆栈,而是复制到其他位置,并在堆栈上放置指向该位置的指针。然而,这完全取决于实施。在任何一种情况下,结构数据都会被复制两次。如果结构相对较小,则不应存在可测量的差异,尽管如果结构大几兆字节,差异可能会变得显著。

这两个函数都没有良好的设计。这两个函数的问题是堆栈可能是空的。在这种情况下,函数具有未定义的行为,很难确定是否是这种情况

在C语言中,更好的函数定义如下

int StackTop( Stack *ps, StackEntry *pe )
{
    int success = ps->top != 0;

    if ( success )
    {
        *pe = ps->entry[ps->top-1];
    }

    return success;
}
StackEntry * StackTop(Stack *ps)
{

    return &ps->entry[ps->top-1];
}

如果您不关心函数的未定义行为,因为还有一个函数报告堆栈是否为空,那么您应该考虑另一个函数实现,它将允许改变堆栈中存储的值。这样的函数看起来像

int StackTop( Stack *ps, StackEntry *pe )
{
    int success = ps->top != 0;

    if ( success )
    {
        *pe = ps->entry[ps->top-1];
    }

    return success;
}
StackEntry * StackTop(Stack *ps)
{

    return &ps->entry[ps->top-1];
}