2017-01-30 70 views
1

我在C. 读一本非常流行的斯坦福文档*有关链表这里面一个简单的函数,建立具有三个成员的简单LL。我没有得到的唯一的东西,我感到困惑的是,它说它将head指针存储在“本地堆栈变量”中。但是,head指针被分配在堆中!请看看代码,并帮助我理解为什么它是一个本地堆栈变量?堆栈变量混淆使用C

/* 
Build the list {1, 2, 3} in the heap and store 
its head pointer in a local stack variable. 
Returns the head pointer to the caller. 
*/ 
struct node* BuildOneTwoThree() { 

struct node* head = NULL; 
struct node* second = NULL; 
struct node* third = NULL; 

head = malloc(sizeof(struct node)); // allocate 3 nodes in the heap 
second = malloc(sizeof(struct node)); 
third = malloc(sizeof(struct node)); 

head->data = 1; // setup first node 
head->next = second; // note: pointer assignment rule 
second->data = 2; // setup second node 
second->next = third; 
third->data = 3; // setup third link 
third->next = NULL; 

// At this point, the linked list referenced by "head" 
// matches the list in the drawing. 
return head; 
} 

该文件提供了如何绘制链接列表在内存中的样子。我不明白为什么head指针绘制在堆栈区域!

enter image description here

*:http://cslibrary.stanford.edu/103/LinkedListBasics.pdf,页5和6

+5

你在混淆“头部指针”和“头部指针指向的东西”。 – immibis

+0

请您详细说明一下吗?代码是说'头'指针是本地的功能。哪个局部变量?所有变量('head','second'和'third')堆在一起 –

+3

这个头指针**变量**,*就像那个函数中的所有其他变量*一样,都是自动的(在你的白话中,它们活着这个想法就是这样,在范围退出时,变量'head'到期并且不再存在,因此它的值被丢失了。那么,如果你做了*会不会将'head'中的值作为函数结果返回给调用者,然后调用者将其存储起来?除非有其他人保留这个值(就像你通过'返回'给调用者那样),否则它永远丢失了,并且有了它,任何机会都可以“让”你的链表的初始节点。 – WhozCraig

回答

4

但是,这头指针在堆中分配!

不完全是,指针指向的内存部分是堆中的内容。指针本身存储在你的函数堆栈中。

在图中,堆栈空间中只显示head,但指针secondthird也位于堆栈中。这里指的是指向包含地址的变量的指针。这些变量指向的地址就是堆中的内容。

由于head->next被分配到second,你有两个指针指向同一件事。和third一样。请注意,head->next是一个存储在堆中的指针,并指向另一个堆内存地址。它与second相同,它是一个存储在堆栈中的指针,其地址指向堆内存位置(同样与head->next相同)。因此,另一种列表的方式是只分配第一个(head)并使用它的next指针直接分配存储地址的以下元素。与使用什么(与直接指向第二和第三个元素的指针)相比,它的缺点是你失去了这个直接地址。您需要访问第一个和第二个以查找第三个地址。

1

它被存储在“局部变量堆栈”的头指针。但是这个 头指针是在堆中分配的!

每个节点包含一个数据部分和指针部分。上面说的是头的指针部分将指向第一个节点(位于堆中)。但是,头指针变量本身位于堆栈中。

头指针的目的只是为了保持跟踪的第一个节点,并且还可以通过使用其持有它的地址来访问它。