声明和定义结构体有什么区别?

6
struct {
    char a;
    int b;
} x;

为什么要像这样定义一个结构体,而不是直接声明它呢:
struct x {
    char a;
    int b;
};
5个回答

18
在第一种情况下,只有变量 x 可以是那种类型——严格来说,如果你定义了另一个与之相同的结构体 y,它将成为另一种类型。因此,当您永远不需要任何其他相同类型的变量时,可以使用此类型。请注意,您不能将任何东西强制转换为该类型,声明或定义具有使用该类型的原型的函数,甚至动态分配该类型的变量 - 没有名称用于该类型。
在第二种情况下,您不定义变量 - 您只定义了一个类型 struct x,然后可以使用该类型创建所需数量的变量。这当然是更常见的情况。通常与 typedef 结合使用或关联。
typedef struct x
{
    char a;
    int b;
} x;

通常,您应该使用更具信息性的标签名称和类型名称。对于结构体标记(第一个“x”)和typedef名称(第二个“x”),使用相同的名称是完全合法和安全的。

第一近似而言,当您使用普通的“struct x {...};”符号时(无论是否同时定义变量),C++会自动为您“创建typedef”。有关与术语“第一近似”相关的所有注意事项的详细信息,请参见下面的广泛评论。感谢所有帮助我澄清这一点的评论人员。


不了解第一个案例的详细信息,感谢您指出。 - chester89
好的解释。并且还要注意,对于第一个,不能将其放在命名空间范围内。 - Johannes Schaub - litb
@litb:你是在说你不能这样做吗:namespace z { struct { ... } x; },然后引用它 using z::x;,例如?如果是这样,为什么?如果不是,请澄清一下。 - Jonathan Leffler
是的,这就是我想说的。但在用户定义的命名空间内声明它并不特殊。您也可以不在全局命名空间范围内声明 x。原因是:x 将具有外部链接性,但其类型没有链接性。为了使声明有效,如果 x 具有链接性,则其类型必须具有链接性。但是,如果 x 是类成员或局部变量,则它没有链接性,因此其类型也不需要具有链接性(这个限制是由于实现中的名称重整困难而存在的,如果我没记错的话)。 - Johannes Schaub - litb
我也会投票支持一个“[+]显示更多”的功能,特别是对于像这样的答案。我将稍微编辑一下答案,以使“C++自动提供typedef”是现实的一个粗略但相当有效的近似值,并指出实际情况在评论中有所涉及。 - Jonathan Leffler
显示剩余7条评论

4
在第一个例子中,你在声明一个变量。在第二个例子中,你在声明一个类型。我认为更好的方法是:
typedef struct tag_x {
    char a;
    int b;
} x;

1
好的,但是关于这个问题:为什么你要以某种方式定义一个结构体而不是另一种方式? - Rob Kennedy
为什么要使用 tag_xx 来引用同一件事情。结构体、联合体和枚举标签位于与定义 typedef 的普通标识符命名空间不同的命名空间中,因此不存在冲突 - C++ 会自动创建“typedef struct x { ... } x;”。 - Jonathan Leffler
x my_struct; my_struct.a = 'a'; my_struct.b = 1; 可能需要进行编辑以包括用法:x my_struct; my_struct.a = 'a'; my_struct.b = 1; - ThePosey
1
Jonathan:严格来说,在C++中编译器不会为您创建typedef,它允许您在没有struct关键字的情况下创建类型的实例,但这与typedef不同。这里有微妙和不太微妙的区别。在代码中:'typedef struct x { int a; } y; void x() {} void y() {}',声明x函数是正确的,因为它不会与struct x发生冲突。另一方面,y不能被重新声明为函数,因为它将与typedef定义发生冲突。 - David Rodríguez - dribeas
@dribeas:哇!我毫不怀疑你是对的。我认为尝试你展示的内容会是糟糕的编码,但这从来没有阻止过任何人故意或者无意中编写这样的代码。就OP而言,“有效地”修饰的语句可能足够准确,不至于严重误导——而你的注释在有疑问时进行了澄清。感谢提供信息。 - Jonathan Leffler

4

第一个定义了一个名为“x”的变量,其类型是一个未命名的结构。

第二个定义了一个名为x的结构体,但没有定义任何使用它的内容。


2
第一种等同于
struct unnamed_struct {  char a;    int b;};
unnamed_struct x;

只是结构体类型没有名称。


1
只有在C++中才能这样写,而在C语言中需要使用“struct unnamed_struct x;”。 - Jonathan Leffler

2
两者有不同作用:
struct {
   char a;
   int b;
} x;

声明一个类型为struct { char a; int b; }的变量x
struct x {
   char a;
   int b;
};

声明一个名为struct x类型。要获取该类型的变量,您需要稍后执行以下操作:

struct x x = {0};
x x = {0}; // C++ only

第二种方法更常见,因为它可以使声明更短,特别是如果您需要更改结构。如果您永远不需要再次使用该结构并且不想污染命名空间,则使用第一种方法。所以基本上从不使用第一种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接