C样式结构声明

我有一个关于C风格结构的快速问题。 我正在挖掘一些示例代码,并发现以下列方式声明的结构:

typedef struct _STRUCTNAME { // struct contents } STRUCTNAME; 

请注意STRUCTNAME第二次显示缺少下划线。 我的理解是,这将声明一个名为STRUCTNAME的_STRUCTNAME,并且不能再实例化此结构的对象。

但是,情况似乎并非如此。 除了在一个地方之外,这种类型的结构从未在代码中实际实例化:在随机位置使用的此类对象的全局数组中:

 const struct STRUCTNAME ARRAYNAME[] = { // various STRUCTNAMEs declared here }; 

注意再次缺少下划线(我认为是实例化对象的名称?)

我的理解完全没了?

有人能解释一下吗

 typedef struct _STRUCTNAME { // struct contents } STRUCTNAME; 

这段代码做了两件事:

  1. 定义一个名为struct _STRUCTNAME和的结构
  2. 创建名为STRUCTNAME的该结构的typedef

这样做的原因是,在正确的C代码中,您以其他方式声明struct (如上所述)的方式如下:

 struct _STRUCTNAME structInstance; 

但是,使用typedef ,您可以简单地使用以下内容:

 STRUCTNAME structInstance; 

enum声明也是如此。

STRUCTNAME是typedef名称。

_STRUCTNAME是结构的“标记”,它位于不同的名称空间中。

在ANSI标准化之前,结构标记命名空间在许多编译器中并不是独立的,因此为了防止名称与typedef名称冲突,它必须是不同的。 但是,由于标准化,标签名称不需要不同。

你会看到Windows代码中经常使用的这个习惯用语,毫无疑问,因为它在SDK的许多示例中都是这样。 Raymond Chen在一段时间后写了一篇关于它的博客文章:

  • 为什么结构名称与typedef名称不同?

另外,我确信会有一些关于如何为实现保留_STRUCTNAME标识符的注释,因此在任何情况下使用该表单都不是一个好主意。

迈克尔伯尔说:

另外,我确信会有一些关于如何为实现保留_STRUCTNAME标识符的注释,因此在任何情况下使用该表单都不是一个好主意。

好的,我是游戏(但我想要一些格式化,所以你得到一个答案):

语言标准是编译器 – 编写器和编译器 – 用户之间的契约,每个承诺都会做,而不是做某些事情。

大多数以_开头的标识符都是为实现保留的 – 包括所有_开头的后跟大写字母的标识符。 这意味着允许编译器 – 编写器将它们用于任何目的,因为编译器用户已经承诺不使用它们。

违反承诺的编译器用户会得到奇怪的结果。

相反,[适用]标准未为实现保留的所有标识符都保证可供编译器用户使用,因为编译器 – 编写者已承诺不使用它们。

当有效代码获得奇怪的结果时,违反承诺的编译人员会得到退款要求。

我的偏好是在标签名称上添加尾随_ ,包括警卫等,以确保我不在实现的空间内; 从而:

 typedef struct STRUCTNAME_ { // struct contents } STRUCTNAME; 

(一些纯粹主义者对typedef的皱眉只是语法糖,但C在这里和那里需要一点糖,否则它看起来很平淡。)

我相信你的困惑是为什么 struct定义末尾的标识符列表没有实例化实例。 原因是因为您已包含typedef关键字。

考虑typedef的syantax:

 typedef type-definition identifier; 

你所做的是提供你的struct作为类型定义。 您正在定义类型,而不是创建实例。 将此约束为实例化结构只是定义内联类型的实例:

 struct STRUCTNAME { // struct contents } myStruct, *ptr, alsoMyStruct; 

如果不包含typedef关键字,则标识符只会像往常一样指定实例。

 const struct STRUCTNAME ARRAYNAME[] = { // various STRUCTNAMEs declared here }; 

上面的代码不会为数组的不完整类型编译。 我认为它应该是错误的

 const struct _STRUCTNAME ARRAYNAME[] = ... 

或者,您可以使用typedef而不指定struct关键字

 const STRUCTNAME ARRAYNAME[] =