【问题标题】:Generic list contains garbage values in C通用列表包含 C 中的垃圾值
【发布时间】:2019-12-25 23:53:47
【问题描述】:

所以我想用 C 语言编写一个函数,将泛型数组转换为单个链表。

我写的代码:

typedef struct Node {
    struct Node* next;
    void *value;
} Node;

void insert(Node** root, void* value) {
    Node* new_node = (Node *) malloc(sizeof(Node));
    Node* ptr;
    new_node->value = value;
    new_node->next = NULL;

    if (*root == NULL)
        *root = new_node;
    else {
        ptr = *root;
        while (ptr->next != NULL)
            ptr = ptr->next;
        ptr->next = new_node;
    }
}


Node* arr2list(void* array, size_t length) {
    Node *root = NULL;
    for(int i = 0; i < length; i++) {
        insert(&root,&array[i]);
    }
    return root;
}

我为它写了一个小测试:

int main() {
    int arr[] = { 1, 2, 3, 4, 5 };
    int n = sizeof(arr) / sizeof(arr[0]);
    Node* root = arr2list(arr, n);
    while (root != NULL)
    {
        printf("%d,",*(int*) root->value);
        root = root->next;
    }
    return 0;
}

但我得到垃圾值:-13308,-2145276560,-2145276560,-2145276560,-2145276560,

我似乎找不到导致这些结果的错误。

可能是什么问题?

【问题讨论】:

  • @IłyaBursov 它说:“需要算术或指针类型的 'void' 类型的错误操作数”。
  • 问题的第一个版本似乎是正确的。你为什么改变它?
  • @user3386109 有人建议更改它(虽然它是正确的,但后来他删除了他的评论)。约翰尼,虽然这是一个列表而不是数组。
  • 是的,他错了。问题出在arr2list 的声明中。 void *array 应该是 int *array

标签: c arrays pointers linked-list


【解决方案1】:

您的程序包含&amp;array[i],其中array 在第28 行具有void* 类型。

这不是标准的 C。GCC 接受它并将指针算术视为 char* 算术(可以说是一个坏主意,特别是因为它在诸如此类的示例中助长了混淆)。

由于您的函数arr2list 通过一些未对齐的指针使用数组,因此结果显然是任意值(例如,包含第一个数组元素的一些字节和第二个数组元素的一些字节)。

我会很高兴地说,函数arr2list 必须简单地将一个元素的长度作为参数,但是仅靠这个小的更改本身并不足以使事情正常进行。您的链表类型将指针存储为数据,因此该函数还需要为每个元素分配一个块,并在 Node 中存储指向该元素的指针。

如果您满足于让列表指向数组的元素,那么忘记上面的段落,您几乎有一个可行的解决方案,只需让arr2list 带一个额外的参数size_t elt_size 并改用(char*)array + elt_size*i &amp;array[i].

【讨论】:

  • 我使用C99。那么,如何替换&amp;
  • @vesii void* 算术在任何 C 标准中都没有定义。不在 C89 中,不在 C99 中,也不在 C11 中。如果您使用的是 GCC,请尝试 -std=c99 -pedantic 以获取类似于 C99 编译器的内容。问题不在于您使用的是&amp;,而从根本上说,您的函数arr2list 试图在不知道指针指向的元素大小的情况下偏移指针。
  • 算术是什么意思?在以下链接中,您有一个 void* 的示例:geeksforgeeks.org/generic-linked-list-in-c-2
  • 我所说的“void* 算术”在更长的术语中是“使用void* 指针的指针算术”。这不是 C。GCC 使它像“char* 算术”或“使用char* 指针的指针算术”一样工作,这不是你想要的。编译错误会更好地为您服务,标准 C 编译器会提供该错误。
  • @vesii 换句话说,你的错误类似于 Johnny Mopp 在 cmets 中指出的问题stackoverflow.com/questions/8812690/… 中的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-28
  • 2019-02-27
  • 1970-01-01
  • 2012-09-15
  • 2013-05-07
相关资源
最近更新 更多