【问题标题】:Trouble using "void *" in a linked list在链接列表中使用“void *”时遇到问题
【发布时间】:2014-02-19 04:55:19
【问题描述】:

我有一个如下所示的通用链表:

queue.hpp

typedef struct queue_node
{
    struct queue_node *next;
    struct queue_node *prev;
    void *data;
    int32_t index;
} queue_node;

typedef struct queue 
{
    struct queue_node *head;
    struct queue_node *tail;
    struct queue_node *current;
    int32_t max_entries;
    int32_t num_entries;
} queue;

我认为这很简单,但我很难使用 void *data 来处理任意参数(通常是在别处定义的自定义对象)。当我从节点中提取数据时,我尝试将其转换为所需的对象。在这种情况下,我尝试强制转换为 proc_instruction 以读回我存储在那里的数据 -> 分段错误:

procsim.cpp:

while (total_instructions < 5000 && fscanf(proc_tf, "%x %d %d %d %d\n", 
                          &p_inst->address,
                          &p_inst->type, 
                          &p_inst->dst, 
                          &p_inst->src[0], 
                          &p_inst->src[1]) != EOF) {
      trace_queue = append_node(trace_queue,p_inst); // stores p_inst in new trace_queue node
      trace_queue->current = goto_queue_first(trace_queue); 
      p_inst = (proc_instruction*)trace_queue->current->data; // trying to get stored inst from trace_queue node
      printf("%x %d %d %d %d\n",p_inst->address,p_inst->type, p_inst->dst, p_inst->src[0], p_inst->src[1]);
    }

这里是我附加数据的地方(如果有帮助的话):

队列.cpp

queue *append_node(queue *app_q, void *app_data)
{
    if(!queue_is_empty(app_q))
      app_q->current = goto_queue_last(app_q);

    queue_node *n = (queue_node *)emalloc(sizeof(*n));
    n->prev = app_q->current;
    n->next = app_q->tail;
    app_q->current = goto_queue_last(app_q);
    app_q->current->data = app_data;
    app_q->num_entries++;
    app_q->current->index = app_q->num_entries;

    return app_q;
}

我已经看到人们这样做的示例代码,但我似乎无法理解。我一定在这里犯了一个根本性的错误。谢谢男孩/女孩。

【问题讨论】:

  • 你的“append_node”的目的是将新节点追加到列表的尾部吗?
  • 是 - 然后返回附加新节点的队列。
  • n->prev = app_q->tail; app_q->tail->next = n; app_q->tail =n; n->下一个= NULL;我想这就是你想要的。
  • 我不记得为什么了,但是头部和尾部只是列表结构的一部分。我添加的所有新节点都在头节点和尾节点之间。它似乎有效。

标签: c generics casting linked-list void


【解决方案1】:

似乎 queue_node *current 在“append_node”中不是必需的,因为您想将新节点附加到尾部。

并且我没有看到“app_q”的初始化,我假设 memset(0) 在分配时被调用。

queue *append_node(queue *app_q, void *app_data)
{
    queue_node *n = (queue_node *)emalloc(sizeof(*n));

    memset(n, 0, sizeof(queue_node));
    if ( NULL == app_q->head)
    {
        app_q->head = n;
        app_q->tail = n;
    }
    else
    {
        n->prev = app_q->tail;
        n->next = NULL;

        app_q->tail->next = n;
        app_q->tail = n;
    }

    n->data = app_data;
    n->index = app_q->num_entries;

    return app_q;
 }

【讨论】:

  • 是的,使用 current 是不必要的,我忘了使用 memset(0)。谢谢杰瑞。
【解决方案2】:

好吧,我做了一件愚蠢的事:我使用 g++ 而不是 gcc,这在使用带有“void *”的强制转换时很重要 - c++ 比 c 需要更多的逻辑来做到这一点。现在是代码:

procsim.c

 /* Copy the trace file into a linked list */
int total_instructions = 0;
proc_instruction *p_inst = (proc_instruction *)emalloc(sizeof(*p_inst));
queue *trace_queue = init_queue();
proc_instruction *inst;

while (total_instructions < 5000 && fscanf(proc_tf, "%x %d %d %d %d\n", 
                      &p_inst->address,
                      &p_inst->type, 
                      &p_inst->dst, 
                      &p_inst->src[0], 
                      &p_inst->src[1]) != EOF) {
  trace_queue = append_node(trace_queue,p_inst);
  inst = trace_queue->current->data;    // no need to explicitly cast using gcc
  printf("%x %d %d %d %d\n",inst->address,inst->type, inst->dst, inst->src[0], inst->src[1]);
  trace_queue->current = trace_queue->current->next;
  ++total_instructions;   
}

输出完全符合我的预期,来自 proc_tf 数据文件的数据。

我也忘记通过将当前节点设置为下一个节点来推进列表,所以它一遍又一遍地打印同样的东西。

谢谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 2017-11-17
    • 2021-09-26
    • 2021-04-25
    相关资源
    最近更新 更多