I have to build a linked list with each node being an 16 byte array. Using code that works with single uint8_t values, I slightly modified it to accept the 16 bytes. However, whenever I print the list, all nodes are the last node added. What am I doing wrong?
我必须构建一个链表,每个节点都是16字节数组。使用使用使用单个uint8_t值的代码,我稍微修改它以接受16个字节。但是,每当我打印列表时,所有节点都是最后添加的节点。我做错了什么?
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<math.h>
struct array_deck
{
uint8_t *val;
struct array_deck *next;
};
struct array_deck *head = NULL;
struct array_deck *curr = NULL;
int sizeOfSet;
struct array_deck *create_list(uint8_t *val)
{
struct array_deck *ptr = (struct array_deck*)malloc(sizeof(struct array_deck));
if(NULL == ptr)
return NULL;
ptr->val = val;
ptr->next = NULL;
head = curr = ptr;
return ptr;
}
void print_list(void)
{
struct array_deck *ptr = head;
while(ptr != NULL)
{
printf("\n");
printf("actually added = ");
for (int i = 0; i < 16; i++) {
uint8_t blah = ptr->val[i];
printf("[%2i] ",blah);
}
ptr = ptr->next;
}
printf("\n");
return;
}
struct array_deck *add_to_list(uint8_t *data, bool add_to_end)
{
printf("array to be added = ");
for (int i = 0; i < 16; i++) {
printf("[%2X] ",data[i]);
}
if(NULL == head)
return (create_list(data));
struct array_deck *ptr = (struct array_deck*)malloc(sizeof(struct array_deck));
if(NULL == ptr)
return NULL;
ptr->val = data;
ptr->next = NULL;
if(add_to_end)
{
curr->next = ptr;
curr = ptr;
}
else
{
ptr->next = head;
head = ptr;
}
return ptr;
}
int main(void)
{
printf ("# of arrays >> ");
scanf ("%d", &sizeOfSet);
uint8_t data[16];
for(int i = 1; i<=sizeOfSet; i++){
for (int j = 0; j < 16; j++) {
data[j] = i;
}
printf("\n");
add_to_list(data,true);
}
print_list();
return 0;
}
sample run that builds a linked list with 3 nodes:
使用3个节点构建链表的示例运行:
# of arrays >> 3
array to be added = [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1] [ 1]
array to be added = [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2] [ 2]
array to be added = [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3]
actually added = [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3]
actually added = [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3]
actually added = [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3] [ 3]
Program ended with exit code: 0
2 个解决方案
#1
1
In create_list
and add_to_list
the node data is not being copied correctly. The shown code just stores a pointer to the passed in data instead of making a copy of the data. So the result is that all the nodes end up pointing to the same data
defined in main
and thus result in the same values when printed out.
在create_list和add_to_list中,节点数据没有被正确复制。所显示的代码只是将一个指针存储在数据传递中,而不是复制数据。因此,结果是所有节点最终指向主定义的相同数据,因此在输出时,结果是相同的值。
There are a number of ways to fix this. Some more elegant than others but all requiring the data to be copied.
有很多方法可以解决这个问题。有些比另一些更优雅,但都需要复制数据。
The simplest is to assume fixed size data and declare the node struct with static memory for the data. Like so:
最简单的方法是假设固定大小的数据,并为数据声明具有静态内存的节点结构体。像这样:
#define DATA_BYTES 16
struct array_deck
{
uint8_t val[DATA_BYTES];
struct array_deck *next;
};
And then replace the pointer assignments in the list functions with data copies. For example:
然后用数据拷贝替换列表函数中的指针赋值。例如:
memcpy(ptr->val, val, sizeof(ptr->val));
A more flexible/elegant solution would be to explicitly store the size of the data in the node itself so that you could have variable sized data. And then use dynamic memory allocate (malloc
and friends) to get memory for the node val
.
一个更灵活/更优雅的解决方案是显式地将数据大小存储在节点本身中,这样就可以有可变大小的数据。然后使用动态内存分配(malloc和friends)获取节点val的内存。
#2
4
All of your array_deck
's -> val is pointing to the same memory address - to local variable data
in main. You're overwriting it N times thats it why its printing last values inserted.
array_deck的所有-> val都指向相同的内存地址-指向main中的局部变量数据。你重写了N次这就是为什么它输出最后一个值。
To solve problem you should copy the data
array into new and assign to ptr->val
the new allocated array address.
要解决这个问题,您应该将数据数组复制到新的数组中,并将新分配的数组地址分配给ptr->val。
struct array_deck *add_to_list(uint8_t *data, bool add_to_end)
{
...
struct array_deck *ptr = (struct array_deck*)malloc(sizeof(struct array_deck));
if(NULL == ptr)
return NULL;
ptr->val = malloc(16*sizeof(uint8_t));
memcpy(ptr->val, data, 16*sizeof(uint8_t));
ptr->next = NULL;
...
}
P.S. it would be nice to remove create_list function and do all logic of assigning to head in add_to_list.
另外,删除create_list函数并在add_to_list中执行赋值给head的所有逻辑是很好的。
#1
1
In create_list
and add_to_list
the node data is not being copied correctly. The shown code just stores a pointer to the passed in data instead of making a copy of the data. So the result is that all the nodes end up pointing to the same data
defined in main
and thus result in the same values when printed out.
在create_list和add_to_list中,节点数据没有被正确复制。所显示的代码只是将一个指针存储在数据传递中,而不是复制数据。因此,结果是所有节点最终指向主定义的相同数据,因此在输出时,结果是相同的值。
There are a number of ways to fix this. Some more elegant than others but all requiring the data to be copied.
有很多方法可以解决这个问题。有些比另一些更优雅,但都需要复制数据。
The simplest is to assume fixed size data and declare the node struct with static memory for the data. Like so:
最简单的方法是假设固定大小的数据,并为数据声明具有静态内存的节点结构体。像这样:
#define DATA_BYTES 16
struct array_deck
{
uint8_t val[DATA_BYTES];
struct array_deck *next;
};
And then replace the pointer assignments in the list functions with data copies. For example:
然后用数据拷贝替换列表函数中的指针赋值。例如:
memcpy(ptr->val, val, sizeof(ptr->val));
A more flexible/elegant solution would be to explicitly store the size of the data in the node itself so that you could have variable sized data. And then use dynamic memory allocate (malloc
and friends) to get memory for the node val
.
一个更灵活/更优雅的解决方案是显式地将数据大小存储在节点本身中,这样就可以有可变大小的数据。然后使用动态内存分配(malloc和friends)获取节点val的内存。
#2
4
All of your array_deck
's -> val is pointing to the same memory address - to local variable data
in main. You're overwriting it N times thats it why its printing last values inserted.
array_deck的所有-> val都指向相同的内存地址-指向main中的局部变量数据。你重写了N次这就是为什么它输出最后一个值。
To solve problem you should copy the data
array into new and assign to ptr->val
the new allocated array address.
要解决这个问题,您应该将数据数组复制到新的数组中,并将新分配的数组地址分配给ptr->val。
struct array_deck *add_to_list(uint8_t *data, bool add_to_end)
{
...
struct array_deck *ptr = (struct array_deck*)malloc(sizeof(struct array_deck));
if(NULL == ptr)
return NULL;
ptr->val = malloc(16*sizeof(uint8_t));
memcpy(ptr->val, data, 16*sizeof(uint8_t));
ptr->next = NULL;
...
}
P.S. it would be nice to remove create_list function and do all logic of assigning to head in add_to_list.
另外,删除create_list函数并在add_to_list中执行赋值给head的所有逻辑是很好的。