我具备专业的Java背景和一些(不算太多)的C++知识,最近刚开始学习C语言。但是我惊讶地发现,在C语言中,下面这段代码是无法正常工作的:
struct Point {
int x;
int y;
};
Point p;
p.x = 0;
p.y = 0;
看起来我必须使用struct Point
作为类型或使用typedef
来声明p
。这段代码在C99中有效吗?还是这只是"C++的事情"?
我具备专业的Java背景和一些(不算太多)的C++知识,最近刚开始学习C语言。但是我惊讶地发现,在C语言中,下面这段代码是无法正常工作的:
struct Point {
int x;
int y;
};
Point p;
p.x = 0;
p.y = 0;
看起来我必须使用struct Point
作为类型或使用typedef
来声明p
。这段代码在C99中有效吗?还是这只是"C++的事情"?
typedef
是行不通的(因为这是C语言的工作方式),但在C++中,struct
就是一个默认所有成员都是公共成员的class
,所以可以这样使用。typedef
和struct
或enum
之间有很大的区别,所以被踩了。 - PP.不,结构体并没有定义新类型。您需要的是:
typedef struct {
int x; int y;
} Point;
现在Point是一种新类型,您可以使用:
Point p;
p.x = 0; p.y = 0;
struct Foo
之后,我可以声明一个变量 struct Foo a
。 - Chuckstruct
所引导。 - John Bodestruct Point {
int x;
int y;
};
并且
union Point {
int x;
int y;
};
struct Point
和union Point
。struct
和union
分别表示被指定的类型是结构体类型或联合体类型。struct-or-union identifier
。struct
、union
和enum
之间共享,我甚至听说有些人认为,在foo
被定义为union
但从未定义为struct
的情况下声明struct foo bar;
可能是有效的。不确定当前情况如何,但这是一个混乱的主题。 - R.. GitHub STOP HELPING ICEPoint结构体
就像union Foo
一样,是一种类型。你可以用typedef
给它取别名 - typedef struct Point Point;
。
因此...
Point a tag
struct Point a type
typedef struct {
. . .
} Point_t;
Point_t a type
我经常看到在代码中写下为什么?。毕竟,只是写Point x;
似乎完全合理,那么为什么不能这样做呢?
事实上,早期的C语言实现为标签和其他标识符建立了单独的名称空间。实际上有4个名称空间1。一旦以这种方式定义了语言,就不可能允许结构体标签被用作类型,因为这样所有现有代码中的普通标识符和标签之间的名称冲突将突然出错。
1. 这4个名称空间包括:
-- 标签名称(由标签声明和使用的语法消除歧义);
-- 结构体、联合体和枚举的标签(通过后跟任何一个关键字struct、union或enum来消除歧义);
-- 结构体或联合体的成员;每个结构体或联合体都有一个独立的名称空间用于其成员(通过使用.或->运算符访问成员的表达式的类型来消除歧义);
-- 所有其他标识符,称为普通标识符(在普通声明符或枚举常量中声明)
结构体不是类型。您可以按以下方式从结构体创建一个点:
struct Point p;
p.x = 0;
p.y = 0;
typedef struct _point {
int x;
int y;
} Point;
无论如何,请始终为您的结构体命名,如果您必须前向声明它以便能够具有指向相同类型的结构体或循环依赖关系的指针。
struct mytag { int a; }
struct mytag mystruct;
typedef允许你同时定义一个标签名和一个类型名。类型名可以在不使用struct前缀的情况下使用:
typedef struct mytag { int a; } mytype;
mytype mystruct; // No struct required
在C99中它不起作用,这是一个C++的事情。你必须要么说struct Point
,要么在C中使用typedef。
这就是 C 语言的工作方式。在 C 中,你必须这样说:
typedef struct Point {
int x;
int y;
} Point;
Point
的类型,它会按照你的要求进行操作。你首先需要将Point定义为一种类型,例如:
typedef struct Point {
int x;
int y;
} Point;
这使您可以将Point
用作类型,或者struct Point
I.e:
Point *p;
sizeof(struct Point);
有些人喜欢将结构体的名称与正在创建的类型不同,例如:
typedef struct _point {
...
} Point;
struct _point
,它的本意是作为类型 Point
而非被公开。typedef struct Point { ... } Point;
和typedef struct Point_tag { ... } Point;
。"_tag"的原因是struct之后的标识符位于所谓的“标签命名空间”。 - Steve Jessop
struct Point p;
。你可以使用typedef,但我建议你养成将类型称为struct Point
的习惯。 - PP.