有没有办法在不命名结构的情况下在struct中使用指向struct的指针?

时间:2013-08-11 14:45:05

标签: c struct

目前我正在使用此struct

typedef struct node {
    struct node *prev;
    struct node *next;
    size_t elem_size;
    void *data;
} dll_node;

我想使用指向struct prevnext的2个指针,而不是将struct命名为node,而是使用typedef dll_nodestruct内。我怎么能这样做?

我尝试使用

dll_node *next;

而不是当前的,但我得到错误未知类型名称:'dll_node'。

5 个答案:

答案 0 :(得分:3)

不可能做你正在做的事情。编译器不知道dll_node是什么,因为它确定了分配时结构所需的字节数。这样做:

struct node;

typedef struct node dll_node;

struct node {
  dll_node *next;
  dll_node *prev;
  size_t elem_size;
  void *data;
};

...或者我个人喜欢使用的方法(因为你经常处理结构的指针):

struct node;

typedef struct node *dll_node;

struct node {
  dll_node next;
  dll_node prev;
  size_t elem_size;
  void *data;
};

答案 1 :(得分:2)

避免使用多个标识符来引用相同类型的解决方案是这个成语:

typedef struct dll_node dll_node;

struct dll_node {
  dll_node* prev;
  ...
};

请注意,typedefstruct的转发声明同时发布。

另请注意,这仍然在struct名称空间中定义了一个类型名称,在标识符名称空间中定义了一个类型名称,但这是您在C中可以获得的最佳名称。

答案 2 :(得分:1)

typedef struct node dll_node;

struct node {
dll_node *prev;
dll_node *next;
size_t elem_size;
void *data;
};

如果没有事先命名它是不可能的,因为编译器不知道它是什么,如果它最初没有被声明。

答案 3 :(得分:1)

C编译器需要在使用之前查看声明的类型,因为此信息对解析器至关重要。因此,在定义名称之前根本不可能使用类型。

答案 4 :(得分:0)

我真的不明白,如果我理解你的观点,但我认为你能做的就是实现一些简短的多态struct。在您的情况下,node是一个标记,dllnode是一种类型。标签是引用结构本身中的结构所必需的,这就是为什么你的最后一个语句失败而只有struct node是合法的。您不能在静态设计中拥有动态行为。所以,如果我是你,我会将设计改为:

struct dllnode{
    node super;
    dllnode *next;
    dllnode *prev;
    size_t  elem_size;
    void    *payload;
    uint32_t flag;
};

struct node{
   node   *next;
   node   *prev;
   size_t elem_size;
   void   *payload;
};

因此,您可以在代码中使用基本类型node和多个“子”类型,例如dllnode或您需要的任何其他节点类型!通过将父(节点)作为一个孩子(dllnode)进行转换,您可以在两个结构之间交换值。这是因为C标准表示结构的第一个成员与结构的开头对齐。 例如:

void add_dllnode(struct node *s)
{
    struct dllnode *self = (struct dllnode *) s;
    self->next = s->next;
    self->prev = s->prev;
    self->elem_size = s->elem_size;
    self->payload = s->payload;
    // you can now do treat node as if it's dllnode and probably add it to
    // one of your lists
}

此外,无论何时创建node,您都可以将标记成员调整为NODE_TYPE_DLLNODE_TYPE_OTHER,并将其用作调用的条件,例如:

struct node s;
init_node(s);
...
if(((s->flag) & NODE_TYPE_DLL))
    add_dllnode(s);
else
    ...

...