声明C结构的语法正确方法是什么?

时间:2011-01-15 08:05:29

标签: c syntax struct

我以前看过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;
}

4 个答案:

答案 0 :(得分:34)

嗯,明显的区别在你的main

中得到了证明
struct foo a;
bar b;
baz c;

第一个声明属于非typedef ed struct,需要使用struct关键字。第二个是typedef匿名struct,因此我们使用typedef名称。第三个结合了第一个和第二个:您的示例使用baz(这很方便),但可以轻松地使用struct _baz来达到同样的效果。

更新:larsmans' answer提到了一个更常见的情况,您必须至少使用struct x { }来制作链接列表。第二种情况在这里是不可能的(除非你放弃理智并改为使用void *)因为struct是匿名的,typedef直到{{1}才会发生已定义,无法创建指向struct类型本身的(类型安全)指针。第一个版本适用于此用途,但第三个版本在我的经验中通常是首选。给他一些代表。

更明显的区别在于命名空间放置。在C中,struct标记放在与其他名称不同的名称空间中,但struct名称不是。所以以下是合法的:

typedef

但以下情况并非如此,因为名称struct test { // contents }; struct test *test() { // contents } 的含义不明确:

test

typedef struct { // contents } test; test *test() { // contents } 使名称更短(总是加号),但它将它与变量和函数放在同一名称空间中。通常这不是问题,但除了简单的缩短之外,它是一个微妙的差异。

答案 1 :(得分:28)

这主要取决于个人偏好。我想给新类型一个以大写字母开头的名称并省略struct,所以我通常会写typedef struct { ... } Foo。这意味着我不能写struct Foo

例外情况是struct包含指向其自身类型的指针,例如

typedef struct Node {
    // ...
    struct Node *next;
} Node;

在这种情况下,您还需要声明struct Node类型,因为typedef不在struct定义范围内。请注意,两个名称可能相同(我不确定下划线约定的来源,但我猜旧的C编译器无法处理typedef struct X X;)。

答案 2 :(得分:7)

您的所有用法在语法上都是正确的。我更喜欢以下用法

 /* forward declare all structs and typedefs */
typedef struct foo foo;
.
.
/* declare the struct itself */
struct foo {
  short a;
  int b;
  foo* next;
};

观察到这很容易允许使用typedef本身声明中的struct,甚至是struct相互引用的{{1}}。

答案 3 :(得分:5)

之所以产生混淆,是因为有些声明实际上声明了三个C结构。你需要记住以下两者之间的区别:    1.一个typedef声明,    2.结构定义,和    3.结构声明。

它们都是非常不同的C结构。他们都做不同的事情;但如果你愿意,你可以将它们组合成一个复合构造。

让我们依次看看每个声明。

//================================================
struct foo {
  short a;
  int b;
  float c;
};

这里我们使用最基本的结构定义语法。我们将foo定义为C 类型,以后可以使用以下语法来声明该类型的变量:

foo myFoo;  // Declare a struct variable of type foo.

// ============================================= ======= 下一个声明有点像前面的语法,因为它声明了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;

现在只需用之前的语法替换“foo”,瞧!

typedef struct {
  short d;    
  int e;
  float f;
} bar;

//==================================================================
typedef struct _baz {
  short a;
  int b;
  float c;
} baz;

以上语法等同于以下声明序列。

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;

//========================================================