将 char* 分配给 void* 字段

assigning char* to a void* field

提问人:DravStart 提问时间:8/27/2023 最后编辑:DravStart 更新时间:8/27/2023 访问量:63

问:

我需要创建一个程序来读取文件行并将它们保存在链接队列中。我正在使用一个库,该库在每个节点中使用 void* 数据字段。

当我尝试打印存储的所有行时,程序会重复读取的最后一行,以表示文件中存储的行数。

我认为,由于我传递了指向数据字段的指针,因此每次读取新行时,存储的值都会发生变化。有没有办法预防它?

附加我正在使用的函数以及队列函数和结构。


void* readfile(void* arg){
   FILE* fp;
   fp = fopen((char*)arg, "r");
   if(fp==NULL){
      fprintf(stderr, "Error opening file %s\n", (char*)arg);
      exit(EXIT_FAILURE);
   }

   char* line= malloc(sizeof(char)*BUFSIZE); // #define BUFSIZE 1024

   while(fgets(line, BUFSIZE, fp)!=NULL){
      insert_tail(deque_12, (void*)line);
   }
   puts("File read");
   fclose(fp);
   return NULL; 
}
> deque.h 

typedef struct node{
   void* data;
    struct node *next;
    struct node *prev;
}Node_t;

typedef struct deque{
   Node_t *head;
   Node_t *tail;
}Deque_t;

void insert_tail(Deque_t* d, void* data){

   Node_t *newNode = malloc(sizeof(Node_t*));

   newNode->data = data;
   newNode->next = NULL;

   if(d->head == NULL){
      newNode->prev = NULL;
      d->head = newNode;
   }
   else{
      newNode->prev = d->tail;
      d->tail->next = newNode;
   }
   d->tail = newNode;
}

c 链接列表 malloc void-pointers

评论

0赞 Some programmer dude 8/27/2023
在 C 中,所有指针都可以隐式转换为几乎任何其他指针类型,反之亦然。唯一无法转换的指针是指向函数的指针。因此,您可以毫无问题地为变量赋值。void *void *char *
2赞 wohlstad 8/27/2023
数据缓冲区只有 1,因此队列中的所有元素都指向同一缓冲区。每个元素都需要一个缓冲区。您还需要对每个 ed 缓冲区进行备份,以避免内存泄漏。mallocmallocfreemalloc
1赞 Eric Postpischil 8/27/2023
回复“感觉像,因为我正在传递指向数据字段的指针,每次我读取一个新行时,值都会发生变化”:“我觉得”不是问题描述。价值是否在变化?你有什么证据?您观察到程序的什么行为?具体来说,它打印什么输出,或者你在调试器中看到什么值?你认为你应该看到什么行为?如果需要调试帮助,请编辑问题以提供最小的可重现示例
0赞 DravStart 8/27/2023
@EricPostpischil 该值与每个节点读取的最后一行相同。编辑了问题
1赞 wohlstad 8/27/2023
@DravStart您应该在调用 .另外,不要忘记最终的 s. 顺便说一句 - 这里是错误的,因为它将释放之前的分配。malloclineinsert_tailfreerealloc

答:

0赞 Eric Postpischil 8/27/2023 #1

请考虑以下代码:readfile

    char* line= malloc(sizeof(char)*BUFSIZE); // #define BUFSIZE 1024

   while(fgets(line, BUFSIZE, fp)!=NULL){
      insert_tail(deque_12, (void*)line);
   }

这将为缓冲区分配一块内存,并将其地址分配给 。然后,对于每一行输入,它都会调用一个指向 的新节点。lineinsert_tailline

结果是每个节点都指向同一块内存,即 所指向的内存。line

要解决此问题,您必须为每行的数据分配不同的内存。为此,您可以为循环中或例程中的每一行分配内存,并在成功分配内存后,将数据复制到新分配的内存中。然后,当然,必须将新节点的 设置为指向新分配的内存,而不是 。readfileinsert_taillinedataline

将 char* 分配给 void* 字段

此问题与将值转换为值无关。char *void *