目前我正在使用此struct
。
typedef struct node {
struct node *prev;
struct node *next;
size_t elem_size;
void *data;
} dll_node;
我想使用指向struct
prev
和next
的2个指针,而不是将struct
命名为node
,而是使用typedef dll_node
在struct
内。我怎么能这样做?
我尝试使用
dll_node *next;
而不是当前的,但我得到错误未知类型名称:'dll_node'。
答案 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;
...
};
请注意,typedef
与struct
的转发声明同时发布。
另请注意,这仍然在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_DLL
或NODE_TYPE_OTHER
,并将其用作调用的条件,例如:
struct node s;
init_node(s);
...
if(((s->flag) & NODE_TYPE_DLL))
add_dllnode(s);
else
...
...