data-structures - typedef struct VS struct定义

  显示原文与译文双语对照的内容

我是一个初学者编程新手,但我想知道在定义一个结构而不是使用typedef时,使用typedef有什么不同。 我觉得好像没有什么区别,他们完成了同样的任务。


struct myStruct{
 int one;
 int two;
};

vs 。


typedef struct{
 int one;
 int two;
}myStruct;

时间:

常用的习惯用法是: 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'

可以定义与标识符同名的函数,因为标识符在不同的空间中被保留,但是不能在这些标识符发生冲突的情况下定义具有相同名称的函数。

在 C++ 中,定位符号的规则稍微改变了。 C++ 仍然保留两个不同的标识符空间,但在C 中,当你只定义类标识符空间中的符号时,你不需要提供结构/类关键字:


//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 函数后,编译器无法自动解析结构,或者创建一个对象或者定义该类型的参数,你必须回退到包含struct关键字的参数:


//previous code here...
int main() {
 S(); 
 struct S s;
}

没有指出的另一个差异是给结构一个名称( 例如 。 结构 myStruct ) 还允许你提供结构的正向声明。 因此,在其他一些文件中,你可以编写:


struct myStruct;
void doit(struct myStruct *ptr);

不需要对定义进行访问。 我建议你结合两个示例:


typedef struct myStruct{
 int one;
 int two;
} myStruct;

这使你更简洁方便的类型名称,但仍允许你使用如果你需要完整的结构名称。

在( 不是 C++ ) 中,你必须声明如下结构变量:


struct myStruct myVariable;

为了能够使用 myStruct myVariable;,你可以 typedef:


typedef struct myStruct someStruct;
someStruct myVariable;

你可以将 struct 定义和 typedef 组合在一个声明中,声明一个匿名的structtypedef


typedef struct {.. . } myStruct;

在c语言中,结构的类型说明符关键字,工会和枚举是强制性的, IE 你总是有前缀的名称类型与 struct ( 它的标记 ) union 或者 enum 指的类型。

你可以使用 typedef 来删除关键字,它是一种信息隐藏形式,当对象的实际类型在声明时不再可见。

因此建议( 参见 Linux内核编码风格指南 。第 5章) 只这样做当你真正希望隐藏这些信息,而不仅仅是为了省几击键。

应该使用 typedef的一个例子是一个不透明的类型,它只与相应的访问函数/宏一起使用。

区别在于使用 struct 时。

你必须首先执行以下操作:


struct myStruct aName;

第二种方法允许你删除关键字 struct

 
myStruct aName;

 

typedef 和其他构造一样,用于给出一个新的名称。 在这种情况下,主要是为了使代码更清晰:


struct myStruct blah;

vs 。

 
myStruct blah;

 

如果你使用不带typedef的结构,你将总是有 tor


struct mystruct myvar;

这是非法

 
mystruct myvar;

 

如果你使用了 typedef,你不再需要结构前缀。

structtypedef 是两个截然不同的东西。

struct 关键字用于定义或者引用结构类型。 例如这个:


struct foo {
 int n;
};

创建一个名为 struct foo的新类型。 名字 foo 标签;它很有意义,只有当之前立即 struct 关键字,因为标签和其他标识符在不同的名称空间。 ( 这类似于 C++的namespace 概念,但更受限制。)

尽管名称是 typedef,但它并不定义新类型;它只为现有类型创建一个新名称。 例如给出:

 
typedef int my_int;

 

my_intint 来说是一个新名字, my_intint 完全相同的类型。 同样,给定上面的struct 定义,你可以编写:


typedef struct foo foo;

类型已经有一个名称,struct footypedef 声明给出了相同的名称,foo

语法允许你将 structtypedef 组合到一个声明中:


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;

一些程序员将为结构标记和typedef名称使用不同的标识符。 在我看来,没有理由这样做;使用相同的名称是完全合法的,并且更清楚地表明它们是相同的类型。 如果必须使用不同的标识符,至少要使用一致的约定:


typedef struct node_s {
/*.. . */
} node;

( 个人而言,我倾向于省略 typedef,并将类型引用为 struct bartypedef 保存了一些类型,但它隐藏了一个结构类型。 如果你想让类型不透明,这可能是一件好事。 如果客户端代码按名称引用成员 n,那么它是不透明的;它显然是一个结构,在我看来,它是一个结构,它是一个结构。 但是很多聪明的程序员在这一点上与我不一致。 准备读取和理解编写的代码。)

( C++ 有不同的规则。给定 struct blah的声明时,你可以将类型称为 blah,即使没有 typedef 。 如果你认为这是一个好东西,使用typedef可能会使你的C 代码更多 C++-like -- 。

不能对typedef结构使用正向声明。

结构本身是匿名类型,因此你没有一个实际的名称来转发声明。


typedef struct{
 int one;
 int two;
}myStruct;

这样的转发声明无法正常工作:


struct myStruct;//forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

使用后一个示例,在使用结构时省略了struct关键字。 代码中的任何地方都可以编写:

 
myStruct a;

 

代替

 
struct myStruct a;

 

这保存了一些类型,而且可能更具可读性,但这是一个味道

...