【问题标题】:C structure and malloc functionC结构和malloc函数
【发布时间】:2018-11-05 05:55:30
【问题描述】:

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

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

用此代码替换代码 sn-p 时

newnode->next=(struct node*)malloc(sizeof(struct node));
newnode=newnode->next;
newnode->data=2;
start=start->next;
printf("%d",start->data);

error dissapers..如何证明这一点?

【问题讨论】:

  • 请注意,当您接下来要做的是为它们分配不同的值时,将指针初始化为 NULL 是不必要的(但无害的)。
  • 正如约翰所说,如果这确实是您接下来要做的事情,请直接初始化您的指针。使您的代码更精简,看起来更一致。

标签: c pointers data-structures struct malloc


【解决方案1】:

你在这里覆盖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);

【讨论】:

  • 他知道如何修复它,他的第二个版本做到了。他想知道为什么第一个版本是错误的。
  • @Barmar,好吧,在第二个版本中,OP 正在做同样的错误:start=start->next;(覆盖值)
  • 但这不会导致问题,因为start->next 指向一个有效节点。在第一个版本中,start->next 是一个空指针。
  • @Barmar,我不这么认为:newnode=start=(struct node*)malloc(sizeof(struct node));malloc 的结果被分配给两个指针,无论如何,我不清楚 OP 想要做什么。
  • 但后来他做到了newnode->next=(struct node*)malloc(sizeof(struct node));
【解决方案2】:

在第一个代码中,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() 调用将同时更新newnode newnode->next,因为你已经声明它们是等价的。但这不是分配的工作方式——它所做的只是将newnode->next 的值复制到newnode,它不会将这两个地方链接在一起。

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

newnode = newnode->next;

这会更新newnode,但start 仍然可以并指向第一个节点。当你这样做时

start = start->next;

它也更新start 以指向第二个节点。在这种情况下,start->data 是有效的,它包含您在几行之前分配给 newnode->data 的相同内容。

【讨论】:

    【解决方案3】:

    您是正确的,错误来自 printf("%d",start->data);,您试图在其中取消引用指向 NULL 的指针。

    让我用图形解释一下: 使用前 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 | 
                                                 |_____________|
    

    【讨论】:

    • 好的,我现在进去了。。谢谢你的回答。。很有帮助!!!
    【解决方案4】:

    在你的两个代码中的第一个,你有

    newnode=newnode->next;
    newnode=(struct node*)malloc(sizeof(struct node));
    

    。这些分配中的第一个是无用的:因此分配给newnode 的任何值都在下一行中被另一个替换。此外,nothing 被分配给newnode 最初指向的结构的next 成员。对newnode 的第一个赋值不会以某种方式将其绑定到next 指针,作为指针本身的别名。它只是让newnode 指向同一个东西。

    在第二个代码中,你有:

    newnode->next=(struct node*)malloc(sizeof(struct node));
    newnode=newnode->next;
    

    这更有意义。您首先分配内存并指定newnode->next 指向它,然后更新newnode 以指向新内存。此外,到目前为止,您仍然有 start 指向第一个动态分配的块,因此您仍然可以访问它,并且由于 newnodestart 最初指向相同的结构,相同的值之后可以也可以通过表达式start->next 获得。

    【讨论】:

      【解决方案5】:

      让我评论一下第一个版本的作用:

      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指向的值。

      【讨论】:

        猜你喜欢
        • 2012-09-19
        • 1970-01-01
        • 1970-01-01
        • 2014-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-24
        • 1970-01-01
        相关资源
        最近更新 更多