[英]Why is `typedef struct x x` allowed?
我正在阅读《 现代C》这本书,很惊讶地发现以下代码有效
typedef struct point point;
struct point {
int x;
int y;
};
int main() {
point p = { .x = 1, .y = 2 };
}
但是,这本书没有详细介绍。 这是如何运作的? 为什么main()
中的point
引用typedef
因为struct point
是在此之后定义的?
线typedef struct point point;
做两件事:
struct point
的前向声明 point
struct point
创建类型别名。 如果您需要在结构完全定义之前就知道其退出,则前向声明很有用,例如:
typedef struct x X;
typedef struct y {
int a;
X *x;
} Y;
struct x {
int b;
Y *y;
};
在定义struct foo { ... }
之前,可以在许多地方使用struct foo
。 这称为“不完整类型”。
这很有用,因为它使您可以定义抽象类型:
foo_header.h
struct foo; // abstract
struct foo *foo_create(void);
void do_stuff_with(struct foo *);
void foo_destroy(struct foo *);
这样,库的用户可以使用结构指针和在这些指针上工作的函数,而无需了解结构的实际定义方式,这对于封装非常有用。
它也用于递归类型:
struct node {
int data;
struct node *next; // struct node isn't defined yet!
};
// here the definition of struct node is complete
C支持它,因为它易于实现:要编译使用struct foo *
代码,编译器只需知道指针的大小即可。 它不在乎结构成员。
同样,在您的typedef
示例中,编译器不需要知道结构的详细信息即可为其创建类型别名。
之所以可行,是因为C具有多个名称空间 :
goto
或尾随:
); struct
, enum
和union
标记名称(由struct
, union
或enum
关键字消除歧义): struct
和union
成员的名称(由前导.
或->
消除歧义,每个struct
或union
类型都充当其自己的名称空间,因此不同的struct
和union
类型可以使用相同的成员名称); 因此,您可以在同一代码中使用与标签相同的名称,标签名称,成员名称和常规标识符,并且编译器可以区分它们:
struct x { int x; }; // tag name, member name
void foo( struct x x ) // tag name, all other identifiers
{
if ( x.x ) // all other identifiers, member name
goto x; // label name
// do something here
x: printf( "At label x\n" ); // label name
}
此示例直接来自C标准的6.7.2.3节:
以下替代公式使用typedef机制:
typedef struct tnode TNODE;
struct tnode {
int count;
TNODE *left, *right;
};
TNODE s, *sp;
它向前执行的操作将声明struct,然后为其创建类型别名。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.