我有一个关于C风格结构的快速问题。我正在挖掘一些示例代码并找到以下列方式声明的结构:
typedef struct _STRUCTNAME
{
// struct contents
} STRUCTNAME;
请注意STRUCTNAME第二次显示缺少下划线。我的理解是,这将声明一个名为STRUCTNAME的_STRUCTNAME,并且不能再实例化此结构的对象。
然而,情况似乎并非如此。除了在一个地方之外,这种类型的结构从未在代码中实际实例化:在随机位置使用的此类对象的全局数组中:
const struct STRUCTNAME ARRAYNAME[] =
{
// various STRUCTNAMEs declared here
};
请注意再次缺少下划线(我认为是实例化对象的名称?)
我的理解完全消失了吗?
有人可以解释一下吗?
答案 0 :(得分:7)
typedef struct _STRUCTNAME
{
// struct contents
} STRUCTNAME;
这段代码做了两件事:
struct _STRUCTNAME
和typedef
的结构的STRUCTNAME
。这样做的原因是,在适当的C代码中,您以其他方式声明struct
(如上所述)的方式如下:
struct _STRUCTNAME structInstance;
但是,在typedef
到位的情况下,您只需使用以下内容:
STRUCTNAME structInstance;
enum
声明也是如此。
答案 1 :(得分:4)
STRUCTNAME
是typedef名称。
_STRUCTNAME
是结构的'标签',它位于不同的名称空间中。
在ANSI标准化之前,结构标记命名空间在许多编译器中并不是独立的,因此为了防止名称与typedef名称冲突,它必须是不同的。但是,由于标准化,标签名称不需要不同。
你看到这个习惯用法经常在Windows代码中使用,毫无疑问,因为在SDK的许多例子中都是这样。雷蒙德陈写了一篇关于它的博客文章:
此外,我确信会有一些关于如何为实现保留_STRUCTNAME
标识符的评论,因此在任何情况下使用该表单都不是一个好主意。
答案 2 :(得分:2)
此外,我确信会有一些关于如何为实现保留
_STRUCTNAME
标识符的评论,因此在任何情况下使用该表单都不是一个好主意。
好的,我是游戏(但我想要一些格式化,所以你得到一个答案):
语言标准是编译器 - 编写者和编译器 - 用户之间的契约,每个人都承诺这样做而不做某些事情。
以_
开头的大多数标识符都是为实现保留的 - 包括以_
开头的所有标识符,后跟大写字母。这意味着允许编译器编写者将它们用于任何目的,因为编译器用户已承诺不使用它们。
违反承诺的编译用户会得到奇怪的结果。
相反,[适用]标准不为实现保留的所有标识符都保证可供编译器用户使用,因为编译器 - 编写者已承诺不使用它们。
当有效代码获得奇怪的结果时,违反承诺的编译人员会获得退款要求。
我的偏好是在标记名称上添加一个尾随_
,包括警卫等,以确保我不在实现的空间内;因此:
typedef struct STRUCTNAME_
{
// struct contents
} STRUCTNAME;
(有些纯粹主义者在typedef
上皱眉只是语法糖,但C在这里和那里需要一点糖,否则它看起来很平淡。)
答案 3 :(得分:0)
我相信你的困惑是为什么 struct
定义末尾的标识符列表没有实例化实例。原因是您已添加typedef
关键字。
考虑typedef
的syantax:
typedef type-definition identifier;
您所做的是struct
作为类型定义。您正在定义类型,而不是创建实例。将此约束为实例化结构只是定义内联类型的实例:
struct STRUCTNAME
{
// struct contents
} myStruct, *ptr, alsoMyStruct;
如果不包含typedef
关键字,标识符将照常指定实例。
答案 4 :(得分:0)
const struct STRUCTNAME ARRAYNAME[] =
{
// various STRUCTNAMEs declared here
};
上面的代码不会为数组的不完整类型编译。我认为它应该是错误的
const struct _STRUCTNAME ARRAYNAME[] = ...
或者,您可以在不指定struct keyword
的情况下使用typedefconst STRUCTNAME ARRAYNAME[] =