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

Mar*_*nds 33 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;
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*utz 34

嗯,明显的区别在你的main:

struct foo a;
bar b;
baz c;
Run Code Online (Sandbox Code Playgroud)

第一个声明是一个非的typedefED 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;).


Jen*_*edt 7

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

 /* 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相互之间的参考.

  • 对于我错过的区域+1,并补充一点,如果你在标题中使用`typedef struct foo foo;`并且不提供`struct foo`的定义,那么用户代码将有一个不透明的指针(即它们可以通过` foo*`指向并从库函数接收它们但不能访问内部成员.)这对数据封装很有用,也是一个常见的习惯用法:标准的`FILE*`类型就是这样的一个例子. (4认同)

小智 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)