我是编程新手。前几天我在玩结构和指针......我收到错误。我试图纠正它们。它得到了纠正...但我无法证明为什么首先会出现错误。请帮帮我...
struct node{
int data;
struct node*next;
};
int main(){
struct node *newnode=NULL;
struct node *start=NULL;
newnode=start=(struct node*)malloc(sizeof(struct node));
newnode->data=1;
//code snippet
newnode->next=NULL;
newnode=newnode->next;
newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=2;
start=start->next;//error probably as start->next is perceived as NULL Address
printf("%d",start->data);
return 0;
}
用此代码替换代码段时
newnode->next=(struct node*)malloc(sizeof(struct node));
newnode=newnode->next;
newnode->data=2;
start=start->next;
printf("%d",start->data);
错误令人满意..如何证明这一点?
你在这里覆盖了newnode
的地址
newnode = newnode->next;
您可能希望:
start = malloc(sizeof(struct node));
start->data = 1;
newnode = malloc(sizeof(struct node));
newnode->data = 2;
newnode->next = NULL;
start->next = newnode;
printf("%d", start->data);
在第一个代码中,newnode
和start
都开始指向您分配的同一node
。然后设置newnode->next = NULL;
,这样也会将start->next
设置为NULL
。
然后,您可以执行以下操作:
newnode = newnode->next;
newnode = (struct node*)malloc(sizeof(struct node));
因此,newnode
现在指向不同的节点,但start
仍然指向原始节点。所以start->next
仍然NULL
.然后你做:
start = start->next;
这会将start
设置为NULL
,因此尝试打印start->data
无效,因为您无法取消引用空指针。
malloc()
之前的第一个赋值毫无意义,因为您立即用其他东西替换变量。我猜你认为通过首先重新分配newnode
,malloc()
调用会更新newnode
和newnode->next
,因为你已经声明它们是等效的。但这不是赋值的工作方式——它所做的只是将newnode->next
的值复制到newnode
中,它不会将这两个地方链接在一起。
您的第二个版本通过分配给newnode->next
而不是分配给newnode
来正确。这也分配给start->next
因为newnode
和start
最初指向相同的结构。然后你分配
newnode = newnode->next;
这将更新newnode
,但start
仍然正常并指向第一个节点。当你做
start = start->next;
它也更新start
以指向第二个节点。在这种情况下,start->data
有效,它包含您之前分配给newnode->data
几行的内容。
您是正确的,错误来自您尝试取消引用指向NULL
的指针printf("%d",start->data);
。
让我用图形来解释一下: 使用 FIRS 4 行,您可以得到:
_____________
newnode -> | data = 1 |
start -> | next = null |
|_____________|
这条线newnode->next=NULL;
什么也没做。 然后,newnode=newnode->next;
这样做:
_____________
| data = 1 |
start -> | next = null | newnode -> NULL
|_____________|
然后
newnode=(struct node*)malloc(sizeof(struct node));
newnode->data=2;`
这样做:
_____________ _____________
| data = 1 | | data = 2 |
start -> | next = null | newnode -> | next = null |
|_____________| |_____________|
最后,start=start->next;
像这样设置状态,显然您尝试访问指向NULL
的指针的字段。
_____________
| data = 2 |
start -> null newnode -> | next = null |
|_____________|
在两个代码中的第一个中,你有
newnode=newnode->next; newnode=(struct node*)malloc(sizeof(struct node));
. 这些赋值中的第一个是无用的:因此分配给newnode
的任何值都在下一行中被不同的赋值替换。 此外,没有为newnode
最初指向的结构的next
成员分配任何内容。newnode
的第一个赋值不会以某种方式将其绑定到该next
指针,作为指针本身的别名。 它只是newnode
指向同一件事。
在第二个代码中,您有:
newnode->next=(struct node*)malloc(sizeof(struct node)); newnode=newnode->next;
这更有意义。 首先分配内存并分配指向它newnode->next
,然后更新newnode
以指向新内存。 此外,到目前为止,您仍然start
指向第一个动态分配的块,因此您仍然可以访问它,并且由于newnode
和start
最初指向相同的结构,因此之后也可以通过表达式start->next
获得相同的值。
让我评论一下第一个版本的作用:
newnode=start=(struct node*)malloc(sizeof(struct node));
...
// at this point, newnode and start point to the same node
newnode->next=NULL;
// since start points to the same node as newnode, this means that also
// start->next will be NULL
...
start=start->next; // since start->next is null, start will be null after this statement
printf("%d",start->data); // start is null, so start->null dereferences NULL (undefined behaviour, e.g. a crash or something dubious)
您的第二个版本不同,因为...
newnode->next=(struct node*)malloc(sizeof(struct node));
// this lets newnode->next point to a valid (new) node
// since start==newnode, also start->next will point to this valid (new) node
start=start->next; // afterwards, start will point to the valid (new) node
printf("%d",start->data); // OK; should print 2 then.
我认为您可能会将赋值表达式与"定义别名"混淆:
newnode=newnode->next;
newnode=(struct node*)malloc(sizeof(struct node));
与
newnode->next = (struct node*)malloc(sizeof(struct node));
因为
newnode = newnode->next
没有为 newnode 定义宏或替换文本,以便文本newnode
从此newnode->next
替换为文本。 相反,变量newnode
将获得一个新值,即该节点的成员next
指向的值。