我在C中实现了一个链接列表。这是我创建的一个结构,它代表链表:
typedef struct llist {
struct lnode* head; /* Head pointer either points to a node with data or NULL */
struct lnode* tail; /* Tail pointer either points to a node with data or NULL */
unsigned int size; /* Size of the linked list */
} list;
不是“llist”基本没用。当客户端使用此库并创建新的链接列表时,他将具有以下声明:
list myList;
所以在开口大括号之前输入llist几乎没用,对吧?以下代码基本上执行相同的工作:
typedef struct {
struct lnode* head; /* Head pointer either points to a node with data or NULL */
struct lnode* tail; /* Tail pointer either points to a node with data or NULL */
unsigned int size; /* Size of the linked list */
} list;
答案 0 :(得分:2)
如果要在结构声明中引用它,则需要为结构命名。
typedef struct snode {
struct snode* next;
struct snode* prev;
int id;
} node;
但如果您不在其中引用结构,则无需为其命名。
修改强>
请注意,typedef
和struct
是C中的两个不同的陈述。
struct
用于创建复杂类型:
struct snode {
struct snode* next;
struct snode* prev;
int id;
};
像这样的读取会创建一个名为snode
的结构,该结构存储对自身的两个引用(next
和prev
)以及int
(id
)
typedef
用于制作别名:
typedef struct snode node;
与类似的内容为名为struct snode
的node
创建了一个类型别名。
答案 1 :(得分:1)
是的,你是对的。除了typedef之外,明确命名结构只是习惯或惯例的问题。
请注意,无论如何都没有任何成本,因为llist
不是变量且不占用内存。这就像命名变量i
或index
之间的区别 - 编译后的形式是相同的,但一个可能比另一个更具可读性。
答案 2 :(得分:1)
在 特定情况下没用,但是,如果你想在结构本身中指向那个结构的指针,那么就需要它。
那是因为结构在开始大括号中是已知的,而typedef直到最后一个分号才知道(简单,但在这里足够好)。
所以你需要它,比如:
typedef struct sNode { // structure can be used now
int payload;
struct sNode *next; // cannot use typedef yet
} tNode; // typedef can be used now
答案 3 :(得分:0)
你可以转过来:不是结构标签,但整个typedef是多余的。
struct snode {
struct snode* next;
struct snode* prev;
int id;
};
现在你可以用:
声明一个指针struct snode *ptr;
你甚至可以声明它们的数组:
struct snode mynodes[10];
你必须输入struct关键字,但这不会伤害编译器或人类读者(看看语法突出显示!)。
您甚至可以使用不完整类型声明指向未知类型的指针(此时正在编译):
struct xnode *xptr=NULL;
当您想要为某个库创建API时,这将会派上用场,其中调用者不知道库的实际实现:
struct gizmo *open_gizmo(char *path, int flags);
int fiddle_with_gizmo(struct gizmo *ptr, int opcode, ...);
等等。 typedef会强制头文件将所有内部“广播”到调用者,即使不需要。