Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare union inside a record structure?

I am trying to define the TWaveFormatExtensible type, but I am not sure if am I declaring correctly the Samples union. Here is the original declaration from header file (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;
}

And this is what I've tried:

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;

But that's not correct. How would one declare a union inside a record structure in Delphi?

like image 400
Johny Bony Avatar asked Nov 09 '19 18:11

Johny Bony


People also ask

How do you declare a union within a structure?

You can declare a structure or union type separately from the definition of variables of that type, as described in Structure and union type definition and Structure and union variable declarations; or you can define a structure or union data type and all variables that have that type in one statement, as described in ...

Can we use union inside structure?

A structure can be nested inside a union and it is called union of structures. It is possible to create a union inside a structure.

How do you create a union in C++?

union { int no; char name[20], float price; }; In this, the size of the member, name is more than the size of other members (sr, price) so the size of a union in memory (char × 20 = 20 byte) will be 20 bytes.

How many data can be stored in a union at one time?

Union is used when you have to use the same memory location for two or more data members. It enables you to hold data of only one data member.


1 Answers

The fields of the structure must be in the same order as in the original (C++) declaration. But there's a problem: the original declaration puts the Samples variant in the middle of the record and that is not allowed in Delphi.

You can solve this by declaring the variant part as a separate record and then include that record as a field in the final structure.

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

and then construct the final structure:

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

edit: The documentation for records with variant parts, state:

A record type can have a variant part, which looks like a case statement. The variant part must follow the other fields in the record declaration.

This concerns variant parts without an enclosing record declaration.

However, as Remy Lebeau pointed out, a record with the variant part can be directly declared in the TWaveFormatExtensible declaration as part of the structure, in between other fields:

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

So this can be used as well as the separately declared TWaveFormatExtensibleSamples record.

like image 160
Tom Brunberg Avatar answered Oct 18 '22 01:10

Tom Brunberg