typedef结构与结构定义
这个问题在这里已经有了答案:
常见的习惯用法是:
typedef struct X {
int x;
} X;
它们是不同的定义。 为了使讨论更清晰,我将分割这句话:
struct S {
int x;
};
typedef struct S S;
在第一行中,您将在结构体名称空间中定义标识符S
(而不是C ++意义上的)。 您可以使用它并通过将参数的类型定义为struct S
来定义新定义类型的变量或函数参数:
void f( struct S argument ); // struct is required here
第二行在全局名称空间中添加一个类型别名S
,从而允许您只写:
void f( S argument ); // struct keyword no longer needed
请注意,由于两个标识符名称空间不同,因此在结构体和全局空间中定义S
不是错误,因为它不是重新定义相同的标识符,而是在不同的位置创建不同的标识符。
为了使区别更清楚:
typedef struct S {
int x;
} T;
void S() { } // correct
//void T() {} // error: symbol T already defined as an alias to 'struct S'
您可以使用结构的相同名称定义一个函数的标识符被保存在不同的空间,但具有相同的名称作为你不能定义一个函数typedef
为这些标识符冲突。
在C ++中,它稍有不同,因为定位符号的规则已经微妙地改变了。 C ++仍然保留两个不同的标识符空间,但与C不同的是,当您只在类标识符空间中定义符号时,不需要提供struct / class关键字:
// C++
struct S {
int x;
}; // S defined as a class
void f( S a ); // correct: struct is optional
搜索规则有哪些更改,而不是定义标识符的位置。 编译器将搜索全局标识符表,并且在S
未找到之后,它将在类标识符内搜索S
前面介绍的代码的行为方式相同:
typedef struct S {
int x;
} T;
void S() {} // correct [*]
//void T() {} // error: symbol T already defined as an alias to 'struct S'
在第二行中定义S
函数之后,结构S不能由编译器自动解析,并且要创建一个对象或定义该类型的参数,必须回退到包含struct
关键字:
// previous code here...
int main() {
S();
struct S s;
}
没有指出另一个区别是给结构一个名称(即struct myStruct)也使您能够提供结构的前向声明。 所以在其他文件中,你可以写:
struct myStruct;
void doit(struct myStruct *ptr);
而无需访问定义。 我推荐的是你结合你的两个例子:
typedef struct myStruct{
int one;
int two;
} myStruct;
这为您提供了更简洁的typedef名称的便利,但仍然允许您在需要时使用完整的结构名称。
struct
和typedef
是两个完全不同的东西。
struct
关键字用于定义或引用结构类型。 例如,这个:
struct foo {
int n;
};
创建一个名为struct foo
的新类型。 名称foo
是一个标签; 只有当它紧挨着struct
关键字时才有意义,因为标签和其他标识符位于不同的名称空间中。 (这与namespace
的C ++概念类似,但限制更多)。
typedef
尽管名称没有定义新的类型, 它仅为现有类型创建一个新名称。 例如,给出:
typedef int my_int;
my_int
是int
的新名称; my_int
和int
是完全相同的类型。 同样,给定上面的struct
定义,你可以写:
typedef struct foo foo;
该类型已经有一个名称, struct foo
。 typedef
声明给出了相同类型的新名称foo
。
该语法允许您将一个struct
和typedef
到一个声明中:
typedef struct bar {
int n;
} bar;
这是一个常见的成语。 现在你可以将这个结构类型作为struct bar
或者仅仅作为bar
引用。
请注意,typedef名称在声明结束前不可见。 如果结构包含一个指向它自己的指针,那么你可以使用struct
版本来引用它:
typedef struct node {
int data;
struct node *next; /* can't use just "node *next" here */
} node;
有些程序员会为struct标记和typedef名称使用不同的标识符。 在我看来,这没有什么好的理由。 使用相同的名称是完全合法的,并且使得它们更清楚,它们是相同的类型。 如果您必须使用不同的标识符,至少应使用一致的约定:
typedef struct node_s {
/* ... */
} node;
(个人而言,我更喜欢省略typedef
并将类型称为struct bar
, typedef
保存了一些输入,但它隐藏了它是一个结构类型的事实,如果您希望该类型是不透明的,这可能是一种好如果客户代码是按名称引用成员n
,那么它不是不透明的;它显然是一个结构,在我看来,把它称为结构是有意义的,但是很多聪明的程序员不同意我在这一点上,准备阅读和理解以任何方式编写的代码。)
(C ++有不同的规则,给定一个struct blah
的声明,即使没有typedef,你也可以引用类型为blah
,使用typedef可能会让你的C代码更像C ++ - 如果你认为这是一个好的事情。)
上一篇: typedef struct vs struct definitions
下一篇: Difference between numeric, float and decimal in SQL Server