【问题标题】:How to declare union inside a record structure?如何在记录结构中声明联合?
【发布时间】:2019-11-09 18:55:25
【问题描述】:

我正在尝试定义 TWaveFormatExtensible 类型,但我不确定我是否正确声明了 Samples 联合。这是头文件(Windows SDK 10.0.17763.0)的原始声明:

typedef struct {
    WAVEFORMATEX    Format;
    union {
        WORD wValidBitsPerSample;       /* bits of precision  */
        WORD wSamplesPerBlock;          /* valid if wBitsPerSample==0 */
        WORD wReserved;                 /* If neither applies, set to zero. */
    } Samples;
    DWORD           dwChannelMask;      /* which channels are */
                                        /* present in stream  */
    GUID            SubFormat;
}

这是我尝试过的:

type
  TWAVEFORMATEX = record
    wFormatTag: Word;
    nChannels: LongWord;
    nSamplesPerSec: Word;
    nAvgBytesPerSec: LongWord;
    nBlockAlign: Word;
    wBitsPerSample: Word;
    cbSize: Word;
  end;

  TWaveFormatExtensible = record
    Format: TWAVEFORMATEX;
    dwChannelMask: LongWord;
    SubFormat: Integer;
    case Word of
      0: (wValidBitsPerSample: Word;);
      1: (wSamplesPerBlock: Word;);
      2: (wReserved: Word;);
  end;

但这是不正确的。如何在 Delphi 的记录结构中声明联合?

【问题讨论】:

  • IIRC,Delphi 7 早于 WAVEFORMATEXTENSIBLE 的发明。是什么阻止您在自己的代码中简单地声明它?
  • @RemyLebeau:如何声明联合样本?
  • P.S. SubFormat 的类型为 GUID(在 Delphi 中为 TGUID),而不是 Integer。成员nChannels 的类型为WORDnSamplesPerSec 的类型为DWORD。除了您应该最好使用本机类型,例如DWORD 成员声明为 DWORD 类型。

标签: delphi winapi delphi-7


【解决方案1】:

结构的字段必须与原始 (C++) 声明中的顺序相同。但是有一个问题:原始声明将Samples 变量放在记录的中间,这在Delphi 中是不允许的。

您可以通过将变体部分声明为单独的记录,然后将该记录作为字段包含在最终结构中来解决此问题。

TWaveFormatExtensibleSamples = record
case Word of
  0: (wValidBitsPerSample: Word;);
  1: (wSamplesPerBlock: Word;);
  2: (wReserved: Word;);
end;

然后构造最终的结构:

TWaveFormatExtensible = record
  Format: TWAVEFORMATEX;
  Samples: TWaveFormatExtensibleSamples;
  dwChannelMask: DWORD;
  SubFormat: TGUID; 
end;

edit:具有变体部分的记录的文档,状态:

一个记录类型可以有一个变体部分,它看起来像一个 case 语句。变体部分必须跟在记录声明中的其他字段之后。

这涉及没有封闭记录声明的变体部分。

但是,正如 Remy Lebeau 所指出的,带有变体部分的 记录 可以直接在 TWaveFormatExtensible 声明中声明为结构的一部分,在其他字段之间:

TWaveFormatExtensible = record
  Format: TWAVEFORMATEX;
  Samples: record
    case Word of
    0: (wValidBitsPerSample: Word;);
    1: (wSamplesPerBlock: Word;);
    2: (wReserved: Word;);
  end;
  dwChannelMask: DWORD;
  SubFormat: TGUID;
end;

所以这可以和单独声明的TWaveFormatExtensibleSamples记录一样使用。

【讨论】:

  • 这种情况下,因为Samples在C声明中不是匿名联合,所以可以将TWaveFormatExtensibleSamples直接合并到TWaveFormatExtensible中,不需要分开:TWaveFormatExtensible = record ... Samples: record case Word of ... end; ... end;
  • 感谢@Remy 的评论
猜你喜欢
  • 2012-05-07
  • 1970-01-01
  • 2012-08-08
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-23
  • 1970-01-01
相关资源
最近更新 更多