可以更改C非指针类型的内存地址吗?

时间:2018-10-29 20:47:45

标签: c pointers memory-management data-structures

为了完全理解它们,我一直在实现一些C数据结构。

这是我对字符串链接列表的定义:

typedef struct str_linked_list {

   const char*                 data;
   struct str_linked_list*     next;

} str_linked_list;

这是删除列表中第n个元素的函数的实现:

void str_remove_at(str_linked_list* list, int index) {
    // Invalid index case
    if (index < 0) {

        fprintf(stderr, "Error, array index < 0\n");
        return;

    } 

    str_linked_list* to_delete; // Always gonna need this
    // Delete head case
    if ( index == 0 ) {

        to_delete = list;
        // If this node is not the last one save the reference to the remaining ones
        if ( to_delete->next != NULL )
            list = list->next;

        //free(to_delete);
        return;

    }
    // General case
    int i = 0;

    str_linked_list* buf = list;

    for (i = 0; i != index-1; i++) {

        if (buf->next != NULL){

            buf = buf->next;

        } else {

            fprintf(stderr, "The list is not that long, aborting operation");
            return;

        }

    }

    to_delete = buf->next;

    if ( to_delete->next != NULL )
        buf->next = to_delete->next;

    free(to_delete);

}

到目前为止,它运行良好,但是我相信我所说的方式无法删除头部,这就是为什么注释free(head)的原因。我已经使用以下代码测试了此代码:

#include "LinkedList.h"

int main() {

    str_linked_list l;
    l.data = "Hello, World";
    l.next = NULL;

    str_remove_at(&l, 1); 


    str_print(&l);

    printf("\n\n");

    str_remove_at(&l, 0);
    str_print(&l);

    return 0;
}

我有点弄清楚,不将列表初始化为指针会使更改存储该变量的内存地址变得困难。我是否必须重新编码lib才能将列表初始化为指针或有什么方法可以将变量的存储位置分配给另一个地址?

总结所有内容,我可以这样更改“ i”的值吗?

#include "stdlib.h"

void change_value(int* i) {
   int* new_alloc = malloc(sizeof(int));
   *new_alloc = 1;
    i = new_alloc;
}

int main() {
    int i = 0;
    change_value(&i);
    return 0;
}

1 个答案:

答案 0 :(得分:3)

对于解决删除列表标题的情况,您有几种选择:

A)将列表作为**list传递,从而允许您从函数内部分配头,即,以str_remove_at(&list, i)调用并在内部使用*list而不是list功能。

B)从函数返回列表的开头,在这种情况下,调用方应执行list = str_remove_at(list, i)

C)要求您的列表的头部有一个“哨兵”元素,该元素永远不会删除,并且实际列表以head->next开始。这“浪费”了一个列表节点,但是当实际的第一个元素不再是特殊情况时,也可以简化其他操作。 (如果您有一个双向链接列表,这样做的好处将会增加。)

D)不用传递指向列表中节点的指针,而要使用单独的str_list_nodestr_linked_list,其中str_list_node是您当前的struct,{{ 1}}和data,以及next具有str_linked_list。然后,当您通过str_list_node *head时,可以更改str_linked_list *list,而不必更改list->head本身。 (此解决方案可能会扩展为其他好处,例如能够存储list用于O(1)追加。)