C语言中为何能通过->访问无变量名的二叉树结构体成员?
关于二叉树指针无变量名访问的疑问
先看这段C语言代码:
#include <stdio.h> #include <stdlib.h> struct node { int data; struct node *left, *right; }; struct node *givetree() { struct node *newnode = (struct node*)malloc(sizeof(struct node)); char choice; printf("Enter data : "); scanf("%d",&newnode->data); printf("\nWanna fill left of %d ? (y/n) : ",newnode->data); scanf("%c",&choice); if(choice == 'y') newnode->left = givetree(); printf("\nWanna fill right of %d ? (y/n) : ",newnode->data); scanf("%c",&choice); if(choice == 'y') newnode->right = givetree(); return newnode; } int main(void) { struct node *root = givetree(); printf("\nThis works : %d",root->left->left->data); return 0; }
疑问
printf("\nThis works : %d",root->left->left->data);这行代码为何能正常运行?该二叉树通过递归创建,root指针接收根节点的指针,但递归函数的局部变量名在函数执行完毕后已销毁,root为何还能访问名为left的结构体成员?我知道这些数据仍存在内存中,但为何没有变量名也能访问?
解答
核心是要分清变量名和内存地址的区别:
- 你用
malloc分配的内存位于堆区,堆内存不会随函数执行结束自动释放,只要没调用free,这块内存里的结构体数据就一直存在。 - 函数里的局部变量
newnode是栈上的指针变量,函数执行完后这个变量名确实会被销毁,但它指向的堆内存地址已经被返回出去了——递归时父节点的newnode->left会接收子节点返回的地址,最终main里的root拿到了根节点的堆内存地址。 root->left->left->data的访问逻辑是顺着地址找:root存着根节点的地址,通过它找到根节点结构体,结构体里的left成员是左子节点的地址,再顺着这个地址找到左子节点,它的left又是下一层节点的地址,最终就能拿到对应节点的data值。整个过程不需要依赖函数里的局部变量名,只要内存地址有效就行。
另外提个小问题:你这段代码里的scanf("%c",&choice)有坑——输入完数字按回车的换行符会被当成%c的输入,导致判断逻辑出错,建议改成scanf(" %c",&choice)(注意前面的空格,用来跳过空白字符)。
内容的提问来源于stack exchange,提问作者Rishav
相关产品推荐
相关产品推荐

