使用函数调用来实现堆栈

时间:2014-02-21 18:42:01

标签: c struct

我对C的这一部分有点不清楚,因为它与我使用的其他语言有点不同,但这可能只是一个愚蠢的问题。我正在尝试实现堆栈。我有节点结构,它有我想传递的信息:

struct position{
   int square[2];
   int counter;
   struct position *prev;
};

所以在main中,我声明并初始化堆栈的底部节点,将*prev设置为NULL,然后声明其余部分。我的问题是,当我尝试将其传递给函数pop时会发生什么?我可以创建一个指向此对象的position对象并返回该对象,但是当函数关闭时它是否会被推离堆栈?或者我应该返回position并将其设置为等于main中的新position对象?如果我决定在函数中创建其中几个节点怎么办?一旦函数关闭,它们会保留吗?

编辑:mah让我想起了我的后续问题,即如果它们不存在于函数之外,我应该使用malloc为它们在内存中创建空间吗?

2 个答案:

答案 0 :(得分:1)

对象的生命周期取决于它们的创建位置;如果你声明一个代码块中的结构(其中一个块是{内的所有内容及其匹配的}),那么一旦执行离开该块,该结构就不再有效。只要结构有效,指向该结构的指针才有效。

对于您所描述的内容,您希望使用malloc()或类似函数动态分配结构。动态分配的数据将保持有效(假设您不覆盖它),直到您free()内存,或直到您的程序终止。这些记忆区域的指针在同一段时间内仍然有效。

考虑:

static struct position *topOfStack = NULL;

void push(struct position *node)
{
    node->prev = topOfStack;
    topOfStack = node;
}

struct position *pop()
{
    struct position *popped = topOfStack;
    if (topOfStack) topOfStack = topOfStack->pref;
    return popped;
}

要使用此功能,您可以:

f() {
    struct position *node = malloc(sizeof(*node));
    /* ... fill in node details ... */
    push(node);
}

请注意,我动态分配了节点。如果我刚刚声明struct position node;,我可以合法地调用push(&node);但是一旦我的函数离开范围,堆栈中就会有一个无效项(这可能会造成严重破坏)。

答案 1 :(得分:0)

  

当我尝试将其传递给pop函数时会发生什么?

这取决于您的pop()函数原型。如果pop的函数原型应该是:

struct position* pop(struct position* stack);
  

我可以创建一个指向此对象的位置对象并返回该对象,但是当该函数关闭时它会被推离堆栈吗?

你的问题很不清楚,它看起来像是对C实例范围的一个很大的误解。基本上,你有两种方法可以在堆栈或堆上分配变量。您正在讨论的范围是堆栈实例范围。

  

如果我决定在函数中创建多个这些节点怎么办?一旦函数关闭,它们会保留吗?

基本上,如果你使用堆栈,它们将在它们声明的范围内生存。在C中,范围由{}定义。例如:

int main() {
    struct position pos1;
    struct position pos2;
    struct position pos3;
    pos3.prev = pos2;
    pos2.prev = pos1;
    pos1.prev = NULL;
    pop(&pos3);
}

你声明了3个变量并将它们关联起来,pop函数只重置了.prev链接。但对于堆栈而言,这种架构并不真正有用,因为它非常有限。

你肯定需要在堆中推送你的实例,因此使用malloc()free()

// push() pseudocode:
// take stack, iterate over each prev until prev is NULL
// allocate prev with malloc() the same way as for "stack" in main()
// insert values in prev
void push(struct position* stack, int* value);

// pop() pseudocode:
// take stack, iterate over each prev until prev->prev is NULL, 
// then keep prev->prev in a temporary variable
// set prev to NULL
// return temporary variable (former prev->prev)
struct position* pop(struct position* stack);

int main() {
    int value[2];
    struct position* stack = malloc(sizeof(struct position));
    // value is what you want to push to the stack
    value[0] = 42;
    value[1] = 42;
    push(stack, value);
    value[0] = 2;
    value[1] = 20;
    push(stack, value);
    struct position* pos;
    pos = pop(stack);
    // do something with pos->value
    free(pos);
}

在那里创建一个指向节点的指针,在该节点中为堆分配一些内存。 push()函数正在分配一些新内存,为.prev的地址分配stack新空间并用该值填充该内存。 pop()应该到达最后一个值之前的值,将其指针重置为该值,然后返回该值。

当然,我只是在这里提供概念和想法,我要离开你去实际的实现。但有一条建议,不是使用包含数组的square,而是在结构中使用两个单独的值,这样可以使第一个实现更简单。