【问题标题】:Linked list, but every "next" pointer points to the next node's "next" pointer链表,但每个“next”指针都指向下一个节点的“next”指针
【发布时间】:2017-10-05 03:35:53
【问题描述】:

我正在尝试编写一个链表,其限制是节点内部的指针必须指向下一个节点的指针。有了这个限制,我将如何访问节点内的变量? 说定义了节点

struct Node {
    int val;
    void *next;
}

但是对于每个节点,假设我们有 currentNode 和 nextNode,我们将 void *next 值设为

currentNode.next = &(nextNode.next);

您将如何创建它并有效地访问每个节点?

【问题讨论】:

  • 为什么有这个限制?为什么将其声明为void* 而不是struct node **
  • next 指针是结构体开头的某个offset。虽然非常不鼓励,但您始终可以通过一些简单的算术获得指向结构的指针。
  • 这是一个学校作业,我们不能修改结构。我们必须编写一个与这样的列表一起使用的函数,但我需要先了解列表是如何工作的,然后才能这样做。我找不到像这样的列表的任何示例。限制在这个赋值中,void *next 指向下一个节点中的下一个字段,而不是节点的开头。即 curr_node.ptr = &(next_node.ptr);不是 curr_node.ptr = &next_node
  • @Barmar 我想你的意思是struct Node *
  • 如果这是限制,那很好。更改结构,使“下一个”指针位于结构的开头: 'struct Node {void *next; int val;}' 完成。

标签: c pointers linked-list


【解决方案1】:

您可以通过使用offsetof 运算符减去next 的偏移量来获得指向Node 的指针。

struct Node *nextNode = (struct Node *)((char *)currentNode.next - offsetof(Node, next));
int nextVal = nextNode->val;

如果你使用的是 C99,它没有内置 offsetof(),你可以使用这个传统的宏:

#define offsetof(st, m) ((size_t)&(((st *)0)->m))

这是技术上未定义的行为(请参阅Does &((struct name *)NULL -> b) cause undefined behaviour in C11?),但它通常有效。

【讨论】:

  • 我相信这基本上是@Some程序员老兄给出的答案。
  • 请注意,offsetof 在 C89 中不可用。
  • 没错,但我认为有一个宏已经使用了多年。
  • 我们使用的是 c99。偏移方法有效!但是我们不能使用偏移功能,所以我不得不计算大小并手动编写。
  • @Avallauch 我已将宏定义添加到答案中。
【解决方案2】:

使用适当的结构,以便固有地满足限制:

struct Node {
    void *next;
    int val;
}

不需要显式的指针运算。

【讨论】:

    【解决方案3】:

    我正在根据您的要求实施链接列表。希望这会帮助你。在此链接列表中,节点内的每个指针都指向下一个节点指针。

    请在你的程序stdio.h、memory.h和stdlib.h的顶部添加这3个头文件

    struct Node {
        int val;
        void *next;
    };
    
    
    void main(void)
    {
      typedef struct Node NODE;
      NODE *f,*p,*q = NULL;
      int i = 1;
      /* First create your first node here */
      f = (NODE *)malloc(sizeof(NODE));
      f->next = f;
      f->val = 0;
      p = f;
    
    /* now lets create link list with 10 nodes */
      while( i < 10 )
      {
        q = (NODE *)malloc(sizeof(NODE));
        q->next = q;
        q->val = i++;
        p->next = q->next; /* first node is pointing to the next node pointer */
        p = q;
      }
    
        /* search the link list and print its value */
        p = f; /* now p is pointing to the first node of the link list */
        i = 0;
        /* first print the value of first node here */
        printf("Node :%d and val = %d\n", i, p->val);
        while(p->next != p)
        {
          printf("Node :%d and val = %d\n", i++, ((NODE *)(p->next))->val);
          p = p->next;
        }
    }
    

    这个程序的输出;

    节点 :0 和 val = 0

    节点 :1 和 val = 1

    节点 :2 和 val = 2

    节点 :3 和 val = 3

    节点:4 和 val = 4

    节点:5 和 val = 5

    节点:6 和 val = 6

    节点:7 和 val = 7

    节点:8 和 val = 8

    节点 :9 和 val = 9

    【讨论】:

    • 谢谢!这种可视化有所帮助。我设法让它工作,这个想法是你使用像 (&(node->ptr) - 0x4); 这样的偏移量。这将指向一个节点的开头。
    猜你喜欢
    • 1970-01-01
    • 2014-12-13
    • 1970-01-01
    • 2020-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-19
    相关资源
    最近更新 更多