带标签的结构允许您创建实例(或在c中调用的任何实例)。如果typedef是为了将struct关键字替换为类型名,那么每次使用typename时,您不是在说您正在用类型名替换struct关键字吗?例子:
typedef struct {
int x;
int y;
}TypeName;
int main()
{
TypeName instance; // isn't this the same as writing struct instance; ?
return 0;
}
那么,当你在结构体上使用typedef时,它是如何工作的呢?
它定义了一个没有名称的结构体,然后将TypeName
作为同一结构体的名称。
如果你愿意,你可以把它想象成编译器为你创建了一个随机的名字(有些编译器实际上是这样做的):
typedef struct __TOTALLY_RANDOM_NAME_wieryweuoi3u4t23423cogh234283 {
int x;
int y;
}TypeName;
int main()
{
struct __TOTALLY_RANDOM_NAME_wieryweuoi3u4t23423cogh234283 instance;
return 0;
}
如果结构定义没有标记,则每次出现时都是不同的类型。例如:
int main(void)
{
struct { double a, b; } x;
struct { double a, b; } y = { 0, 0 };
x = y;
}
将得到错误消息,因为x
和y
是不兼容的类型。
当使用typedef
时,它为类型创建一个新名称。它不像重复先前源代码的宏替换;它是概念类型的名称,而不是源代码的名称。所以这个源代码不会得到错误消息:
int main(void)
{
typedef struct { double a, b; } T;
T x;
T y = { 0, 0 };
x = y;
}
其他相同的结构定义被认为具有不同类型的一个原因是我们可能希望将它们用于不同的目的。例如,我们可能有typedef struct { double v[2]; } Point;
用两个坐标表示平面上的点,typedef struct { double v[2]; } Complex;
用实部和虚部表示复数,我们希望在程序中将它们作为单独的类型处理。
struct { int x; int y; }
是一个匿名结构类型,它与其他具有完全相同成员的结构类型不同(即使它们共享相同的二进制布局)。
下列声明之后:
struct {
int x;
int y;
} a, b;
struct {
int x;
int y;
} c;
则变量a
与变量b
具有相同类型,但与变量c
不具有相同类型。出于同样的原因,下面的代码有变量d
的冲突类型:
extern struct {
int x;
int y;
} d; // external declaration of `d`.
extern struct {
int x;
int y;
} d; // INVALID: conflicting external declaration of `d`.
struct {
int x;
int y;
} d = { 23, 42 }; // INVALID: conflicting definition of `d`.
类型定义(使用typedef
关键字声明)对于将标识符定义为"typedef names"很有用。它们是指定类型的同义词。typedef
声明不创建任何新类型,它只创建现有类型的同义词。在其他声明中出现的typedef名称表示原始类型。这对于捕获匿名类型特别有用,以便它们可以在多个声明中使用。例如,在以下声明之后:
typedef struct {
int x;
int y;
} TypeName;
TypeName a, b;
TypeName c;
extern TypeName d;
extern TypeName d;
TypeName d = { 23, 42 };
typepedef名称TypeName
表示匿名结构类型。变量a
、b
、c
和d
都具有相同的匿名结构类型。变量d
的外部声明与其定义之间没有冲突。
作为另一个例子,在以下声明之后:
typedef struct {
int a;
int b;
} Type1, Type2, TypeArr1[10];
typedef Type2 TypeArr2[10];
typedef struct {
int a;
int b;
} Type3;
extern Type1 a;
extern Type2 a; // no conflict with previous declaration of variable `a`.
extern Type3 a; // INVALID! conflicting types for variable `a`.
extern TypeArr1 arr;
extern TypeArr2 arr; // no conflict with previous declaration of variable `arr`.
Type1
和Type2
表示相同的类型。TypeArr1
表示长度为10的数组类型,其元素类型与Type1
表示的相同。TypeArr1
和TypeArr2
表示相同的数组类型(数组长度和元素类型相同)。Type1
和Type3
表示不同的类型,因此它们在变量a
声明中的使用是冲突的。