我对C的这一部分有点不清楚,因为它与我使用的其他语言有点不同,但这可能只是一个愚蠢的问题。我正在尝试实现堆栈。我有节点结构,它有我想传递的信息:
struct position{
int square[2];
int counter;
struct position *prev;
};
所以在main中,我声明并初始化堆栈的底部节点,将*prev
设置为NULL
,然后声明其余部分。我的问题是,当我尝试将其传递给函数pop
时会发生什么?我可以创建一个指向此对象的position
对象并返回该对象,但是当函数关闭时它是否会被推离堆栈?或者我应该返回position
并将其设置为等于main中的新position
对象?如果我决定在函数中创建其中几个节点怎么办?一旦函数关闭,它们会保留吗?
编辑:mah让我想起了我的后续问题,即如果它们不存在于函数之外,我应该使用malloc为它们在内存中创建空间吗?
答案 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
,而是在结构中使用两个单独的值,这样可以使第一个实现更简单。