【问题标题】:Can you change the memory address of a C non-pointer type?您可以更改 C 非指针类型的内存地址吗?
【发布时间】:2018-10-29 20:47:44
【问题描述】:

为了完全理解它们,我一直在实现一些 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;
}

我发现不将列表初始化为指针会使更改存储该变量的内存地址变得困难。我是否必须重新编码库才能将列表初始化为指针或有没有办法可以将变量的内存位置分配给另一个地址?

总结一下,我可以这样改变“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;
}

【问题讨论】:

  • 你能进一步总结你的问题吗?您是在问类似的问题,例如,您可以更改int i 的地址吗?
  • 与你的分配方式保持一致,不会出现这样的问题。
  • 就是这样,要改一下,谢谢。
  • 与你的实际问题无关,看来if ( to_delete-&gt;next != NULL )是错误的,无条件赋值buf-&gt;next = to_delete-&gt;next会达到正确的行为。

标签: c pointers memory-management data-structures


【解决方案1】:

你有几种方法可以解决删除列表头部的情况:

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

B) 从函数返回列表的头部,在这种情况下调用者应该做list = str_remove_at(list, i)

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

D) 不要将指针传递给列表中的节点,而是使用单独的 str_list_nodestr_linked_liststr_list_node 是您当前的 structdatanext,以及 @ 987654333@ 有str_list_node *head。然后,当您通过 str_linked_list *list 时,您可以更改 list-&gt;head 而无需更改 list 本身。 (此解决方案可以扩展为具有其他好处,例如能够存储 str_list_node *tail 以进行 O(1) 附加。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多