[英]I don't understand pointers, addresses and scopes
以下是我编写的代码段,目前正在打印中挣扎。
在我的主要方法中,我使用有效输入两次调用函数insertPoint
,例如: insertPoint(42); insertPoint(56);
insertPoint(42); insertPoint(56);
并获得以下输出:
A.1 42
B.3 2686700
但是在B.3,我希望它也返回值42,但不会。 我假设2686700指向内存中的某个地址。
#include <stdio.h>
#include <stdlib.h>
struct point {
int value;
struct point* next;
};
struct point *root;
int insertPoint(int value) {
// Graph is empty, set new root
if(root == 0){
struct point newRoot;
newRoot.value = value;
root = &newRoot;
(*root).value = value;
printf("A.1 %d \n", (*root).value); // "A.1 42"
return value;
}
printf("B.3 %d \n", (*root).value); // "B.3 2686700"
/* rest of code here; irrelevant since related variables are not changed */
}
有人知道为什么会这样吗? 任何建设性的评论/答案表示赞赏。
如果下降者会向我提供反馈,我也将不胜感激,为什么他们认为我的问题不合适。
如果采用if (root == 0)
分支,则root
将指向struct point newRoot;
这是在if
分支主体内部的堆栈上分配的。 newRoot
结构在离开分支的主体和函数的主体之后(在您的情况下,在return value;
之后)超出范围return value;
声明。 但是,全局指针变量root
将继续指向内存中的该位置(堆栈上)。 该位置上的堆栈存储器的内容很可能会被其他一些代码覆盖,因此从该位置读取point
(成员)值(例如,通过root
指针)将导致不确定的行为,这就是为什么要得到这种结果的原因。
您可能打算动态分配新的根,例如:
if(root == 0) {
root = (point *) malloc(sizeof(point));
root->value = value;
root->next = NULL;
printf("A.1 %d \n", root->value); // "A.1 42"
return value;
}
别忘了设置next
指针,因为默认情况下它不会为NULL
(除非也许不是malloc
而是使用calloc
来对返回的内存进行零初始化,从而在大多数平台上有效地使next
的值等于NULL
)。 另外,不要忘记释放动态分配的任何内存:使用malloc
, calloc
或realloc
分配的任何内存都必须稍后使用free
。
您的代码具有未定义的行为,因为它允许在范围之外使用指向局部变量的指针。
它发生在这里:
struct point newRoot;
...
root = &newRoot;
问题在于,一旦函数到达}
关闭if
语句, root
就会失效。 对其的任何取消引用都是未定义的行为。 因此,当您这样做时
printf("B.3 %d \n", (*root).value);
您访问无效指针指向的内存。
幸运的是,解决此问题的方法很简单:使用malloc
而不是newRoot
为链表元素分配内存:
if(root == 0){
root = malloc(sizeof(struct point));
root->value = value;
printf("A.1 %d \n", (*root).value); // "A.1 42"
return value;
}
当然,在退出程序之前,您需要使用malloc
free
分配的malloc
,以避免内存泄漏。
您创建struct point newRoot;
在函数内部的堆栈上。 由于它在堆栈上,因此在退出此函数时将其销毁。 此后,任何使用其指针( *root
)的操作都应给出未定义的结果。
您必须了解,堆栈超出范围时,堆栈中的内容会消失
所以
root = &newRoot;
这里newRoot
在堆栈中。 函数结束newRoot
结束-指针无效
使用malloc
创建newRoot
对象,这样我可以使函数调用的寿命更长
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.