【问题标题】:C style struct declarationC 风格的结构声明
【发布时间】:2011-07-25 05:21:20
【问题描述】:

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

typedef struct _STRUCTNAME
{
   // struct contents
} STRUCTNAME;

请注意,STRUCTNAME 第二次出现时缺少下划线。我的理解是,这将声明一个名为 STRUCTNAME 的单个 _STRUCTNAME,并且不能实例化该结构的更多对象。

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

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

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

我的理解完全不成立吗?

谁能解释一下?

【问题讨论】:

    标签: c struct


    【解决方案1】:
    typedef struct _STRUCTNAME
    {
       // struct contents
    } STRUCTNAME;
    

    这段代码做了两件事:

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

    这样做的原因是,在适当的 C 代码中,声明 struct(如上)的方式如下:

    struct _STRUCTNAME structInstance;
    

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

    STRUCTNAME structInstance;
    

    enum 声明也是如此。

    【讨论】:

      【解决方案2】:

      STRUCTNAME 是 typedef 名称。

      _STRUCTNAME 是结构的“标签”,位于不同的命名空间中。

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

      您会在 Windows 代码中看到这个惯用语,这无疑是因为它在 SDK 的许多示例中都是如此。 Raymond Chen 不久前写了一篇关于它的博文:

      另外,我敢肯定会有一些关于如何为实现保留_STRUCTNAME 标识符的问题,所以在任何情况下使用这种形式都不是一个好主意。

      【讨论】:

      • 您能解释一下“标签”是什么意思吗?
      • "tag" 只是 C 标准用于为结构、联合或枚举赋予名称/标识符的术语。
      【解决方案3】:

      Michael Burr 说:

      另外,我敢肯定会有一些关于如何为实现保留_STRUCTNAME 标识符的 cmets,所以在任何情况下使用这种形式都不是一个好主意。

      好的,我在玩游戏(但我想要一些格式,以便你得到答案):

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

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

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

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

      当有效代码得到奇怪的结果时,违背承诺的编译器编写者会收到退款要求。

      我的偏好是在标签名称后面加上_,包括守卫等,以确保我远离实现的空间;因此:

      typedef struct STRUCTNAME_
      {
         // struct contents
      } STRUCTNAME;
      

      (一些纯粹主义者不赞成 typedefs 仅仅是语法糖,但 C 需要在这里和那里加一点糖,否则它看起来很乏味。)

      【讨论】:

        【解决方案4】:

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

        考虑typedef 的语法:

        typedef type-definition identifier;
        

        您所做的是提供您的struct 作为类型定义。您不是创建实例,而是定义一个类型。将此与实例化实例进行对比,其中结构只是定义内联类型:

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

        当您不包含 typedef 关键字时,标识符只是像往常一样指定实例。

        【讨论】:

          【解决方案5】:
          const struct STRUCTNAME ARRAYNAME[] = 
          {
             // various STRUCTNAMEs declared here
          };
          

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

          const struct _STRUCTNAME ARRAYNAME[] = ...
          

          您也可以使用 typedef 而不指定 struct 关键字

          const STRUCTNAME ARRAYNAME[] =
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-04-08
            • 1970-01-01
            • 1970-01-01
            • 2021-12-03
            • 2021-12-13
            • 1970-01-01
            • 2018-05-13
            相关资源
            最近更新 更多