我以前看过C结构以几种不同的方式声明.为什么会这样,如果有什么,每个都有什么不同?
例如:
struct foo {
short a;
int b;
float c;
};
typedef struct {
short d;
int e;
float f;
} bar;
typedef struct _baz {
short a;
int b;
float c;
} baz;
int main (int argc, char const *argv[])
{
struct foo a;
bar b;
baz c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Chr*_*utz 34
嗯,明显的区别在你的main
:
struct foo a;
bar b;
baz c;
Run Code Online (Sandbox Code Playgroud)
第一个声明是一个非的typedef
ED struct
和需要struct
使用关键字.第二个是typedef
匿名的struct
,所以我们使用这个typedef
名字.第三个结合了第一个和第二个:你的例子使用baz
(它很方便)但可以很容易地使用struct _baz
相同的效果.
更新:larsmans的回答提到了一个更常见的情况,你必须至少使用它struct x { }
来制作一个链表.第二种情况在这里是不可能的(除非你放弃理智并使用void *
替代),因为它struct
是匿名的,并且typedef
直到struct
定义时才会发生,使你无法制作一个(类型安全的)指向struct
打字本身.第一个版本适用于此用途,但第三个版本在我的经验中通常是首选.给他一些代表.
命名空间放置的一个更微妙的区别.在C中,struct
标记放在与其他名称不同的名称空间中,但typedef
名称不是.所以以下是合法的:
struct test {
// contents
};
struct test *test() {
// contents
}
Run Code Online (Sandbox Code Playgroud)
但以下情况并非如此,因为名称的含义不明确test
:
typedef struct {
// contents
} test;
test *test() {
// contents
}
Run Code Online (Sandbox Code Playgroud)
typedef
使名称更短(总是加号),但它将它与变量和函数放在同一名称空间中.通常这不是问题,但除了简单的缩短之外,它是一个微妙的差异.
Fre*_*Foo 29
这主要取决于个人偏好.我喜欢给新类型一个以大写字母开头的名字并省略struct
,所以我经常写typedef struct { ... } Foo
.那意味着我不能再写了struct Foo
.
例外情况是a struct
包含指向其自身类型的指针,例如
typedef struct Node {
// ...
struct Node *next;
} Node;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您还需要声明struct Node
类型,因为typedef
它不在struct
定义范围内.请注意,这两个名称可能是相同的(我不确定下划线约定的来源,但我想旧的C编译器无法处理typedef struct X X;
).
您的所有用法在语法上都是正确的.我更喜欢以下用法
/* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
short a;
int b;
foo* next;
};
Run Code Online (Sandbox Code Playgroud)
观察到这很容易允许使用typedef
已经在其内部的声明struct
,甚至struct
相互之间的参考.
小智 5
之所以产生混淆,是因为有些声明实际上声明了最多三个C结构.您需要记住以下两者之间的区别:1.typedef声明,2.结构定义,以及3.结构声明.
它们都是非常不同的C结构.他们都做不同的事情; 但如果您愿意,可以将它们组合成一个复合构造.
让我们依次看看每个声明.
//================================================
struct foo {
short a;
int b;
float c;
};
Run Code Online (Sandbox Code Playgroud)
这里我们使用最基本的结构定义语法.我们将foo定义为C 类型,以后可以使用以下语法来声明该类型的变量:
foo myFoo; // Declare a struct variable of type foo.
Run Code Online (Sandbox Code Playgroud)
// ================================================ ====下一个声明有点像以前的语法,因为它声明了C类型,但它使用了typedef语法.让我们使用之前的基本声明将其分解为其组件.
typedef foo bar; // Declare bar as a variable type, the alias of foo.
bar myBar; // This is ssemantically the same as: foo myBar;
Run Code Online (Sandbox Code Playgroud)
现在只需用之前的语法替换"foo"即可!
typedef struct {
short d;
int e;
float f;
} bar;
//==================================================================
typedef struct _baz {
short a;
int b;
float c;
} baz;
Run Code Online (Sandbox Code Playgroud)
上面的语法等同于以下声明序列.
struct _baz {
short a;
int b;
float c;
}
typedef _baz baz; // Declare baz as an alias for _baz.
baz myBaz; // Is the same as: _baz myBaz;
//========================================================
Run Code Online (Sandbox Code Playgroud)