C结构和马洛克函数



我是编程新手。前几天我在玩结构和指针......我收到错误。我试图纠正它们。它得到了纠正...但我无法证明为什么首先会出现错误。请帮帮我...

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);

在第一个代码中,newnodestart都开始指向您分配的同一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()之前的第一个赋值毫无意义,因为您立即用其他东西替换变量。我猜你认为通过首先重新分配newnodemalloc()调用会更新newnodenewnode->next,因为你已经声明它们是等效的。但这不是赋值的工作方式——它所做的只是将newnode->next的值复制到newnode中,它不会将这两个地方链接在一起。

您的第二个版本通过分配给newnode->next而不是分配给newnode来正确。这也分配给start->next因为newnodestart最初指向相同的结构。然后你分配

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指向第一个动态分配的块,因此您仍然可以访问它,并且由于newnodestart最初指向相同的结构,因此之后也可以通过表达式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指向的值。

最新更新