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;
这段代码做了两件事:
- 定义一个名为
struct _STRUCTNAME
和的结构 - 创建名为
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[] =