繁体   English   中英

为什么允许`typedef struct xx`?

[英]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或尾随: );
  • structenumunion标记名称(由structunionenum关键字消除歧义):
  • structunion成员的名称(由前导.->消除歧义,每个structunion类型都充当其自己的名称空间,因此不同的structunion类型可以使用相同的成员名称);
  • 所有其他标识符(变量和函数名称,typedef名称,枚举常量等)。

因此,您可以在同一代码中使用与标签相同的名称,标签名称,成员名称和常规标识符,并且编译器可以区分它们:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM