C链接列表 - 在内存块中创建节点

时间:2017-02-28 18:12:57

标签: c list malloc heap

我正在尝试在预先分配的内存块中创建链接列表。简单地说,

  1. 我有一个像这样声明的初始内存池。

    void *block = malloc(1000);
    
  2. 我从这个池中创建了一个链表的头部:

    struct node *root = block;
    
  3. 假设初始块的内存地址是100000.如果我添加一个大小为100的链表节点,这只是从100000开始(因为它是第一个节点,共享第一个节点的内存地址)块)。如果我添加大小为200的第二个节点,则应该从100100开始(在最后一个块的末尾)。下一个将从100300开始,依此类推。

  4. 我将节点添加到列表的方法可以压缩如下:

    void add_node(int size) {
        new_node = malloc(sizeof(struct node));
        struct node *current = root;
        while (current != NULL) { //loop to get to the end of the linked list
            ...stuff (irrelevant to this question)...
            current = current->next;
        }
        new_node->value = size;
        current->next = new_node;
    }
    

    节点定义非常通用:

    struct node {
       int value;
       int free;
       struct node *next;
    };
    

    主要方法如下:

    int main(void) {
        create_block(1000);
        add_node(100);
        add_node(200);
        print_all();
    }
    

    print_all只是遍历并打印出内存地址:

    void print_all() {
        printf("%ld (block start)\n", block);
        struct node* current = root;
        while (current != NULL) {
            printf("%ld (%d)", current->value);
            current = current->next;
        }
    }
    

    但是,添加值为100和200的节点时,内存地址如下:

    25770205072(块开始) 25770205072(100个节点的位置 - 这没关系) 25769968848(200节点的位置 - 不行。这应该是25770205072 + 100) 25770204784(剩余700个内存节点的位置 - 不行。这应该是25770205072 + 100 + 200)

    我做错了什么的线索?我尝试了几种不同的方法而没有任何运气。

    感谢您的时间!我非常感谢你的任何帮助。

3 个答案:

答案 0 :(得分:0)

警告:由于您没有显示池代码,这可能不是一个完整的解决方案,但add_node有一些错误。

您必须设置new_node->next = NULL

在循环结束时,current可能为null,除非“无关紧要的东西......”保证非空。在这种情况下,它无关紧要。

您需要一个额外的变量(例如prev

另请注意,由于add_node正在调用malloc,因此它会绕过您的内存池,因此您不能对地址抱有太多期望。

这是我认为你需要的[请原谅无偿的风格清理]:

void
add_node(int size)
{
    struct node *new_node = malloc(sizeof(struct node));
    struct node *current;
    struct node *prev;

    // loop to get to the end of the linked list
    prev = root;
    for (current = root;  current != NULL;  current = current->next) {
        // ... stuff(irrelevant to this question) ...
        prev = current;
    }

    new_node->value = size;
    new_node->next = NULL;

    // NOTE: this assumes root is _always_ non-null
#if 0
    prev->next = new_node;
#else
    if (prev != NULL)
        prev->next = new_node;
    else
        root = new_node;
#endif
}

答案 1 :(得分:0)

实际上,这很简单。我确实使用了@Ajay Brahmakshatriya提到的 - “你可以保留一个从根开始并按大小递增的计数器” - 并创建一个从根开始的新长度,并且每次都按大小递增。我没有将新节点设置为新的已分配内存blob,而是将其设置为旧地址+大小(并适当增加地址)。现在工作正常!谢谢!

答案 2 :(得分:0)

我只是尝试记住“链表”概念...... 它不同于阵列中每个元素位于存储器之前与元素完全相邻/相邻的数组。

我认为每个节点都“动态分配”。程序尝试找到仍然空闲的内存,并且某个当前节点可以位于远离前一节点的位置。但是分配节点的大小块取决于我们如何编写malloc代码,大小来分配它。

所以我认为你的代码没有错......