C结构不定义类型?

我刚开始用专业的Java背景和一些(如果没有太多)C ++知识学习C,我很惊讶这在C中不起作用:

struct Point { int x; int y; }; Point p; px = 0; py = 0; 

似乎我必须使用struct Point作为类型或使用typedef来声明p 。 这段代码在C99中有效吗? 或者这是一个“C ++的东西”?

据我所知,它不应该在没有C99中的typedef情况下工作(因为这只是C的工作方式),但它确实在C ++中工作,因为C ++中的struct只是一个默认情况下公共所有成员的class

不,结构不定义新类型。 你需要的是:

 typedef struct { int x; int y; } Point; 

现在Point是你可以使用的新类型:

 Point p; px = 0; py = 0; 

struct Point就像union Foo类型一样。 您可以使用typedef将其别名为另一个名称 – typedef struct Point Point;

在C中,没有混淆

 struct Point { int x; int y; }; 

 union Point { int x; int y; }; 

这是两种不同的类型,分别称为struct Pointunion Point

C99标准第6.7.2.1节规定:

6结构和联合说明符具有相同的forms。 关键字structunion表示指定的类型分别是结构类型或联合类型。

7 struct-or-union-specifier中struct-declaration-list的存在在转换单元中声明了一个新类型。

因此,它最明确地宣布了一种类型。 C语言中类型名称的语法在6.7.6节中给出,并包含6.7.2中的specifier-qualifier-list ,它采用struct-or-union identifier

这段代码在C99中有效吗? 或者这是一个“C ++的东西”?

不,C99不决定在枚举类型和具有相同名称的联合类型上推广结构类型。 它是一个“C ++的东西”,因为结构和类在C ++中大多是相同的东西,而类对C ++很重要。

所以…

 Point a tag struct Point a type typedef struct { . . . } Point_t; Point_t a type 

我经常看到为什么? 写在行间。 毕竟,仅仅说Point x;似乎是完全合理的Point x; 那你为什么不能呢?

碰巧的是,C的早期实现为标签与其他标识符建立了单独的名称空间 。实际上有4个名称空间1 。 一旦以这种方式定义了语言,就不可能允许将struct标记用作类型,因为所有在普通标识符标记之间具有名称冲突的现有代码将突然出错。


1. 4个名称空间是:
– 标签名称(通过标签声明和使用的语法消除歧义);
– 关键字struct,union或enum)的结构,联合和枚举的标记(通过以下任何方式消除歧义);
– 结构或工会的成员; 每个结构或联合为其成员都有一个单独的名称空间(通过。或 – >运算符用于访问成员的表达式的类型消除歧义);
– 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量)

它在C99中不起作用,它是一个C ++的东西。 你必须要么说struct Point或者在C中使用typedef。

在C中,结构可以有两种名称:标记名称和类型名称。 标签名称只能在带有struct前缀的情况下使用,例如:

 struct mytag { int a; } struct mytag mystruct; 

typedef允许您定义标记名称和类型名称。 可以在没有结构前缀的情况下使用类型名称:

 typedef struct mytag { int a; } mytype; mytype mystruct; // No struct required 

结构不是类型。 您可以从结构创建一个点,如下所示:

 struct Point p; px = 0; py = 0; 

如果要将结构用作类型,则必须键入它。 这适用于C和C ++:

 typedef struct _point { int x; int y; } Point; 

总是给你的struct命名,如果你必须转发声明它能够指向相同类型或循环依赖的结构。

这就是C的工作方式。 在C中你必须说:

 typedef struct Point { int x; int y; } Point; 

然后你会有一个名为Point的类型,可以做你想要的。

在C ++中,它足以按照您的方式定义它。

首先需要使Point类型为:

 typedef struct Point { int x; int y; } Point; 

这允许您将Point用作类型或struct Point

即:

 Point *p; sizeof(struct Point); 

有些人更喜欢使结构的名称与正在创建的类型不同,例如:

 typedef struct _point { ... } Point; 

你会碰到两个。 最后一个例子告诉我,我不应该使用struct _point ,除了Point类型之外,它不应该被暴露。