【问题标题】:Value doesn't assign to struct(Pointers)值未分配给 struct(Pointers)
【发布时间】:2020-12-07 12:32:28
【问题描述】:

当我尝试为 *temp 赋值时,它没有赋值(当我编译时,它不显示 printf 并且 printf 看不到任何赋值)。为什么 ?如何处理更多关于指针的信息(查看它们在我的 IDE 中使用外部应用程序引用的位置...?)

    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #define INT_SIZE sizeof(int) * 8
    
    typedef struct Node Node;
    struct Node
    {
        int value;
        Node *next;
    };
    
    
    typedef struct LinkedList
    {
        Node *head;
    }LinkedList;
    
    
    void Insert(LinkedList **lst, int data)
    {
        Node *temp = malloc(sizeof(Node)); 
        //Check's if is the first Node.
        if ((*lst)->head->next== NULL)
        {       
            (*lst)->head->next = temp;  
            temp->value = data;
            printf("Ok");   
            temp->next = NULL;
        }
    }

还有我的主要功能:

int main()
{
    LinkedList *list = malloc(sizeof(LinkedList)); //Create new linkedlist
    list->head->next = NULL; //Define the head object
    Insert(&list, 20);
    return 0;
}

【问题讨论】:

  • 你怎么称呼Insert
  • 您打算如何在(*lst)-&gt;head 位置得到一个有效的、已分配的、已初始化的项目?如果你不这样做,那是你的问题。
  • 在你的主list-&gt;head没有初始化,你不能访问list-&gt;head-&gt;next
  • @Jose 我已经编辑了帖子并添加了主要功能。
  • 好的,编辑后:list-&gt;head 没有指向任何地方,所以您无法访问lists-&gt;head-&gt;next...

标签: c struct linked-list singly-linked-list function-definition


【解决方案1】:

你动态分配了一个列表

LinkedList *list = malloc(sizeof(LinkedList));

但是它的数据成员head 没有被初始化。结果下一条语句

list->head->next = NULL;

调用未定义的行为,因为使用了具有不确定值的变量 head

没有意义将函数Insert 的第一个参数声明为具有LinkedList **lst 类型,即使用两个间接访问原始列表。像这样声明函数要好得多

int Insert( LinkedList *list, int data );

要检查列表是否为空,您至少必须写如下

    if ( ( *lst )->head == NULL )

此外,如果列表不为空,您的函数什么也不做。

注意,一般来说你应该检查一个新节点的分配是否成功。

函数可以通过以下方式定义

int Insert( LinkedList *list, int data )
{
    Node *temp = malloc( sizeof( Node ) );
    int success = temp != NULL;

    if ( success )
    {       
        temp->value = data;
        temp->next  = list->head;
        list->head = temp;
    }

    return success;
}

不需要动态分配列表本身。你可以写

LinkedList list = { .head = NULL };

Insert( &list, 20 );

请注意,您需要编写一个释放所有已分配内存的函数。例如

void Delete( LinkedList *list )
{
    while ( list->head != NULL )
    {
        Node *temp = list->head;
        list->head = list->head->next;
        free( temp );
    }
}

这是一个演示程序。

#include <stdio.h>
#include <stdlib.h>

typedef struct Node Node;
struct Node
{
    int value;
    Node *next;
};
    
    
typedef struct LinkedList
{
    Node *head;
} LinkedList;

int Insert( LinkedList *list, int data )
{
    Node *temp = malloc( sizeof( Node ) );
    int success = temp != NULL;

    if ( success )
    {       
        temp->value = data;
        temp->next  = list->head;
        list->head = temp;
    }

    return success;
}

void Delete( LinkedList *list )
{
    while ( list->head != NULL )
    {
        Node *temp = list->head;
        list->head = list->head->next;
        free( temp );
    }
}

void Display( const LinkedList *list )
{
    for ( const Node *current = list->head; current != NULL; current = current->next ) 
    {
        printf( "%d -> ", current->value );
    }
    
    puts( "null" );
}

int main(void) 
{
    LinkedList list = { .head = NULL };
    
    const int N = 10;
    
    for ( int i = N; i != 0; i-- )
    {
        Insert( &list, i );
    }
    
    Display( &list );
    
    Delete( &list );
    
    return 0;
}

它的输出是

1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> null

如果您的编译器不支持指定初始化,则代替此声明

    LinkedList list = { .head = NULL };

你可以写

    LinkedList list = { NULL };

如果你想在函数Insert的时候将新节点追加到列表的尾部可以看下面的方式

int Insert( LinkedList *list, int data )
{
    Node *temp = malloc( sizeof( Node ) );
    int success = temp != NULL;

    if ( success )
    {       
        temp->value = data;
        temp->next  = NULL;
        
        Node **current = &list->head;
        while ( *current ) current = &( *current )->next;
        
        *current = temp;
    }

    return success;
}

【讨论】:

    【解决方案2】:

    你的代码有很多错误

    主要:

    LinkedList *list = malloc(sizeof(LinkedList)); //Create new linkedlist
    list->head->next = NULL; //Define the head object
    

    错误是因为list-&gt;head没有初始化,所以设置list-&gt;head-&gt;next有一个未定义的行为

    还有一个逻辑问题,一个空列表是空的=>没有节点,正确的初始化是:

    list->head = NULL;
    

    在插入中:

    if ((*lst)->head->next== NULL)
    

    如果列表为空,这也是无效的,因为(*lst)-&gt;head 为 NULL(经过上述更正后)。

    同样没有else分支,函数必须始终插入新节点。

    要以正确的方式实现,需要知道必须在哪里进行插入,您的列表是 fifo、lifo 还是节点根据值进行排序?

    假设一个节点总是插入到头部:

    void Insert(LinkedList **lst, int data)
    {
        Node *temp = malloc(sizeof(*temp)); 
    
        temp->value = data;
        temp->next = (*lst)->head;
        (*lst)->head = temp;
    }
    

    注意使用双指针是没用的,你可以有:

    void Insert(LinkedList *lst, int data)
    {
        Node *temp = malloc(sizeof(*temp)); 
    
        temp->value = data;
        temp->next = lst->head;
        lst->head = temp;
    }
    
    int main()
    {
        LinkedList *list = malloc(sizeof(*list)); //Create new linkedlist
        list->head = NULL;
        Insert(list, 20);
        return 0;
    }
    

    最后:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Node {
      int value;
      struct Node *next;
    } Node;
        
        
    typedef struct LinkedList {
      Node *head;
    } LinkedList;
    
    void Insert(LinkedList *lst, int data)
    {
        Node *temp = malloc(sizeof(*temp)); 
    
        temp->value = data;
        temp->next = lst->head;
        lst->head = temp;
    }
    
    void pr(const LinkedList *lst)
    {
      const Node * l = lst->head;
      
      while (l != NULL) {
        printf("%d ", l->value);
        l = l->next;
      }
      putchar('\n');
    }
    
    int main()
    {
        LinkedList *list = malloc(sizeof(*list)); //Create new linkedlist
        list->head = NULL;
        Insert(list, 20);
        pr(list);
        Insert(list, 10);
        pr(list);
        return 0;
    }
    

    编译和执行:

    /tmp % gcc -Wall l.c
    /tmp % ./a.out
    20 
    10 20 
    /tmp % 
    

    【讨论】:

    • 谢谢!我已经根据您的强调对我的代码进行了一些编辑,它确实有效!我可以分享我的代码。
    • 欢迎你,当然如果你想在末尾插入一个新节点而不是头部你必须修改 Insert
    • 你为什么建议不要使用双指针?它们是链表的最佳选择,因为它们使实现更加简洁。
    • @klutt 对于目前的情况他们是没用的,我从来没有说过一般情况下是这样的......或者可能是我的答案不够清楚?
    • @bruno 是的,你是对的。我快速阅读了答案。
    【解决方案3】:

    您正在尝试使用内存而不分配它。 LinkedList * 指向一个有效的(动态分配的)结构,但head 指向无处(没有为Node 保留空间),所以一旦你尝试写它,seg fault。

    你有两个选择:

    • 使用mallochead 预留空间,就像使用LinkedList 一样
    • 不将head 声明为指针并在 堆栈/全局 (Node head)。

    Node *next; 也是如此,请考虑是否希望指针在其余代码中指向已经有效的 Node

    另一个问题是您没有释放动态内存,不确定您的代码是否只是一个示例或者您确实存在内存泄漏。

    【讨论】:

    • 很高兴能得到反对投票的解释
    【解决方案4】:

    您尚未为list-&gt;head 分配内存,这意味着您无法访问或修改list-&gt;head-&gt;next

    您应该首先为列表的头部分配内存:

    int main()
    {
        LinkedList *list = malloc(sizeof(LinkedList)); //Create new linkedlist
        list->head = malloc(sizeof(Node)); //Create head
        list->head->next = NULL; //Define the head object
        Insert(&list, 20);
        return 0;
    }
    

    【讨论】:

    • 从技术上讲,它会起作用,但这不是一个好的解决方案
    猜你喜欢
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多