[英]I don't understand pointers, addresses and scopes
Following is a code snippet, I have written and I am currently struggling with my print-outs. 以下是我编写的代码段,目前正在打印中挣扎。
In my main method I call the function insertPoint
twice with valid input, for example: insertPoint(42); insertPoint(56);
在我的主要方法中,我使用有效输入两次调用函数
insertPoint
,例如: insertPoint(42); insertPoint(56);
insertPoint(42); insertPoint(56);
and get the following output: 并获得以下输出:
A.1 42
B.3 2686700
At B.3 however I would expect it to also return the value 42, but it doesn't. 但是在B.3,我希望它也返回值42,但不会。 I assume 2686700 refers to some address in the memory.
我假设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 */
}
Does someone have an idea why this happens? 有人知道为什么会这样吗? Any constructive comment/answer is appreciated.
任何建设性的评论/答案表示赞赏。
I would also appreciate, if the downvoters would provide me feedback, why they found my question inappropriate. 如果下降者会向我提供反馈,我也将不胜感激,为什么他们认为我的问题不合适。
If the if (root == 0)
branch is taken, root
will point to struct point newRoot;
如果采用
if (root == 0)
分支,则root
将指向struct point newRoot;
which is allocated on the stack inside the body of the if
branch. 这是在
if
分支主体内部的堆栈上分配的。 The newRoot
structure goes out of scope after leaving the body of the branch and the body of the function, in your case after the return value;
newRoot
结构在离开分支的主体和函数的主体之后(在您的情况下,在return value;
之后)超出范围return value;
statement. 声明。 However, the global pointer variable
root
will keep pointing to that location in memory (on stack). 但是,全局指针变量
root
将继续指向内存中的该位置(堆栈上)。 The contents of stack memory at that location will most likely be overwritten by some other code, hence reading a point
(member) value from that location (eg via the root
pointer) will result in undefined behaviour, which is why you get such results. 该位置上的堆栈存储器的内容很可能会被其他一些代码覆盖,因此从该位置读取
point
(成员)值(例如,通过root
指针)将导致不确定的行为,这就是为什么要得到这种结果的原因。
You probably meant to dynamically allocate the new root, eg: 您可能打算动态分配新的根,例如:
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;
}
Don't forget to set the next
pointer, as it will not by default be NULL
(unless perhaps instead of malloc
you use calloc
which zero-initializes the returned memory, effectively making the value of next
equal to NULL
on most platforms). 别忘了设置
next
指针,因为默认情况下它不会为NULL
(除非也许不是malloc
而是使用calloc
来对返回的内存进行零初始化,从而在大多数平台上有效地使next
的值等于NULL
)。 Additionally, don't forget to deallocate any memory you allocate dynamically: any memory allocate with malloc
, calloc
or realloc
must be deallocated later using free
. 另外,不要忘记释放动态分配的任何内存:使用
malloc
, calloc
或realloc
分配的任何内存都必须稍后使用free
。
Your code has undefined behavior because it lets a pointer to local variable be used outside the scope. 您的代码具有未定义的行为,因为它允许在范围之外使用指向局部变量的指针。
It happens here: 它发生在这里:
struct point newRoot;
...
root = &newRoot;
The problem with this is that once the function reaches the }
closing the if
statement, root
becomes invalid. 问题在于,一旦函数到达
}
关闭if
语句, root
就会失效。 Any dereference of it is undefined behavior. 对其的任何取消引用都是未定义的行为。 Hence when you do this
因此,当您这样做时
printf("B.3 %d \n", (*root).value);
you access memory pointed to by an invalid pointer. 您访问无效指针指向的内存。
Fortunately, the fix to this problem is simple: use malloc
instead of newRoot
to allocate memory for the linked list element: 幸运的是,解决此问题的方法很简单:使用
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;
}
Of course you would need to free
the memory you allocate with malloc
before exiting the program in order to avoid memory leaks. 当然,在退出程序之前,您需要使用
malloc
free
分配的malloc
,以避免内存泄漏。
You create struct point newRoot;
您创建
struct point newRoot;
on stack inside a function. 在函数内部的堆栈上。 Since, it is on stack, it is destroyed on exit from this function.
由于它在堆栈上,因此在退出此函数时将其销毁。 Any use of its pointer (
*root
) should give undefined result after that. 此后,任何使用其指针(
*root
)的操作都应给出未定义的结果。
You must understand that stuff on the stack disappears when it goes out of scope 您必须了解,堆栈超出范围时,堆栈中的内容会消失
SO 所以
root = &newRoot;
Here newRoot
is on the stack. 这里
newRoot
在堆栈中。 End of function - End of newRoot
- So the pointer is invalid 函数结束
newRoot
结束-指针无效
Use malloc
to create the newRoot
object so I can live longer that the function call 使用
malloc
创建newRoot
对象,这样我可以使函数调用的寿命更长
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.