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

ca1c2owp  于 2023-06-28  发布在  其他
关注(0)|答案(4)|浏览(120)

我以前见过几种不同的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;
}
rjjhvcjd

rjjhvcjd1#

那么,明显的区别在main中得到了证明:

struct foo a;
bar b;
baz c;

第一个声明是un-typedef艾德struct,需要使用struct关键字。第二个是typedef艾德匿名struct,因此我们使用typedef名称。第三个结合了第一个和第二个:您的示例使用了baz(这是方便的短),但可以轻松地使用struct _baz达到相同的效果。
更新:larsmans的回答提到了一个更常见的情况,你必须至少使用struct x { }来创建一个链表。第二种情况在这里是不可能的(除非你放弃理智而使用void *),因为struct是匿名的,而typedefstruct被定义之前不会发生,所以你没有办法创建一个指向struct类型本身的(类型安全的)指针。第一个版本对于这种使用效果很好,但根据我的经验,第三个版本通常是首选的。给予他点面子。
一个更微妙的区别是名称空间的位置。在C语言中,struct标记被放置在与其他名称不同的命名空间中,但typedef名称则不是。以下是法律的的:

struct test {
  // contents
};

struct test *test() {
  // contents
}

但下面的例子不是,因为test的名称是不明确的:

typedef struct {
  // contents
} test;

test *test() {
  // contents
}

typedef使名称更短(总是一个加号),但它将其放在与变量和函数相同的命名空间中。通常这不是一个问题,但这是一个微妙的区别,超出了简单的缩短。

wbgh16ku

wbgh16ku2#

这主要是个人喜好的问题。我喜欢给新类型起一个以大写字母开头的名字,并省略struct,所以我通常写typedef struct { ... } Foo。这意味着我不能写struct Foo
例外情况是当struct包含指向其自身类型的指针时,例如

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

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

dsekswqp

dsekswqp3#

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

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

注意,这很容易允许在struct本身的声明中使用typedef,甚至对于相互引用的struct

ztmd8pv5

ztmd8pv54#

之所以会产生混淆,是因为一些声明实际上声明了多达三个C结构。您需要记住以下两者之间的区别:

  1. typedef声明
    1.结构定义,以及
    1.结构声明。
    它们都是非常不同的C结构。他们都做不同的事情;但是如果你愿意的话,你可以把它们组合成一个复合结构。
    让我们依次查看每个声明。
struct foo {
  short a;
  int b;
  float c;
};

这里我们使用最基本的结构定义语法。我们正在定义一个C类型,并在tag命名空间中将其命名为foo。以后可以使用以下语法声明该类型的变量:

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

下一个声明在global命名空间中为类型提供了另一个名称(别名)。让我们使用前面的基本声明将其分解为组件。

typedef struct foo bar;   // Declare bar as a variable type, the alias of foo.

bar myBar;         // No need for the "struct" keyword

现在只需将“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 struct _baz baz;  // Declare baz as an alias for _baz.

baz myBaz;               // Is the same as: struct _baz myBaz;

相关问题