是一个结构{…}; 一个类型或一个未命名的变量?
在文件范围,以下是类型声明还是未命名变量?
struct student_s { char* name; int age; double height; struct student_s* next; };
如果是类型定义,那么有什么区别:
typedef struct student_s { char* name; int age; double height; struct student_s* next; };
?
(背景:请参阅我的答案将变量从全局更改为本地 – C ,我相信第一个引入了一个未命名的变量,然后由编译器对其进行优化。)
注意 :该问题已被标记为可能重复的结构成员标识符放在什么范围内? 但我相信我不是在询问有关成员范围的问题,而是询问有关声明实际创造的内容。 然而。 回答C ++中’struct’和’typedef struct’的区别? 解释我的问题。
根据C
标准,结构声明的forms如
struct student_s { char* name; int age; double height; struct student_s* next; };
是一种类型的声明。 引用C11
,章节§6.7.2.1
struct-or-union-specifier中struct-declaration-list的存在在转换单元中声明了一个新类型。 struct-declaration-list是结构或联合成员的一系列声明。 […]
C
标准不要求为该类型创建变量 (命名或未命名)。
在你的第二个片段中,你实际上( 尝试 )将typedef
为空 。 但是,如果您将代码段更改为
typedef struct { //.....members } student_s ;
你将创建一个类型 student_s
( typedef
到一个未命名的结构类型),你可以在以后使用它。
FWIW,我们从不谈论过这里创建的变量。 这都是关于类型的 。
第一个声明声明了一个类型。 在声明之后,类型struct student_s
是已知的,您可以声明该类型的变量或指向它的指针:
struct student_s student1; struct student_s *pStudent;
即使编译,第二个声明也很奇怪。 常见的用法是:
typedef struct { char* name; int age; double height; struct student_s* next; } studend_t;
它将别名student_t
声明为匿名结构。 然后可以直接使用它:
student_t student1; student_t *pStudent;
但第二个例子是编译(即使有警告),并且是第一个!
它真正做的是为struct student_s
声明一个void别名。 typedef被忽略并产生一个警告: typedef需要一个名称 ,但作为一个副作用,结构被声明,就像在第一个例子中一样。
因此,实际问题的真正答案是除了警告之外没有差别 。
两者都是类型定义。 第二个是一个不完整的。 它不提供名称作为typedef
的参数。 更好的是使用
typedef struct student_s { char* name; int age; double height; struct student_s* next; } student;
关于合法性
typedef struct student_s { char* name; int age; double height; struct student_s* next; };
我已经问过这个问题, `typedef struct foo {int bar};`的合法性
它是一种类型,你不能拥有一个结构的匿名实例。 为了进行比较,这将声明类型struct_type
和该类型的实例struct_instance
:
struct struct_type { /* blah */ } struct_instance;
如果你想要隔离地声明另一个实例(来自类型decl)你将使用
struct struct_type another_instance;
使用typedef – 如果正确完成,与您的示例不同 – 只允许您为类型指定另一个名称,该名称不需要struct
关键字来声明实例:
typedef struct_type MyStruct; MyStruct yet_another_instance;
或者等价的
typedef struct struct_type { /* blah */ } MyStruct;
省略名称( struct_type
)会为您提供一个匿名结构类型,该结构类型只能通过其typedef名称引用。
注1
由于原始struct包含指向其自身类型的next
指针,因此该类型必须在声明成员的位置具有名称 。 因此,您不能使用自键型指针声明匿名结构。 如果您为匿名结构类型指定了一个名为typedef
的名称,那么该名称在成员声明之后才会存在,因此不能在那里使用。
typedef struct /*S*/ { struct S *next; /* T doesn't exist yet, so without S, you can't declare this */ } T;
笔记2
您可以将匿名联合的匿名实例声明为成员:
struct S { union { int i; unsigned u; }; }; struct S s; si = -1; printf("%x\n", su);
但这是一个非常特殊的情况。 我从主要论点中听取了关于这一点的评论,以防它误导。
不同之处在于,对于第一个示例,您必须声明一个如下所示的新变量: struct student_s variable;
但是,对于第二个例子,你可以简单地做student_s variable;
。
struct A { ... }
在struct
命名空间中创建struct
‘可见(它与C ++命名空间没有任何共同之处)。 因此,要访问struct
您必须使用struct
关键字;
struct A a;
使用typedef结构定义时
typedef struct A { ... } B;
变得可见并绑定到B,您可以轻松地创建类似B的公共变量的struct
B a;
如果我错了,请纠正我。