How do I translate a C union into Delphi?

The Pascal equivalent of a C union is known as a variant record.

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.

To declare a record type with a variant part, use the following
syntax:

type recordTypeName = record
  fieldList1: type1;
   ...
  fieldListn: typen;
case tag: ordinalType of
  constantList1: (variant1);
   ...
  constantListn: (variantn);
end;

The first part of the declaration – up to the reserved word case – is
the same as that of a standard record type. The remainder of the
declaration – from case to the optional final semicolon – is called
the variant part. In the variant part,

  • tag is optional and can be any valid identifier. If you omit tag, omit the colon (:) after it as well.
  • ordinalType denotes an ordinal type.
  • Each constantList is a constant denoting a value of type ordinalType, or a comma-delimited list of such constants. No value can
    be represented more than once in the combined constantLists.
  • Each variant is a semicolon-delimited list of declarations resembling the fieldList: type constructions in the main part of the
    record type. That is, a variant has the form:

    fieldList1: type1;

    fieldListn: typen;

where each fieldList is a valid identifier or comma-delimited list of
identifiers, each type denotes a type, and the final semicolon is
optional. The types must not be long strings, dynamic arrays, variants
(that is, Variant types), or interfaces, nor can they be structured
types that contain long strings, dynamic arrays, variants, or
interfaces; but they can be pointers to these types.

Records with variant parts are complicated syntactically but
deceptively simple semantically. The variant part of a record contains
several variants which share the same space in memory. You can read or
write to any field of any variant at any time; but if you write to a
field in one variant and then to a field in another variant, you may
be overwriting your own data. The tag, if there is one, functions as
an extra field (of type ordinalType) in the non-variant part of the
record.


As for the rest, it’s pretty routine: LONGLONG is a 64 bit integer, and UCHAR is unsigned char, or AnsiChar in Delphi.

type
  TFileObjectIDInformation = record
    FileReference: Int64;
    ObjectID: array[0..15] of AnsiChar;
    case Integer of
    0:
      (
        BirthVolumeId: array[0..15] of AnsiChar;
        BirthObjectId: array[0..15] of AnsiChar;
        DomainId: array[0..15] of AnsiChar;
      );
    1:
      (ExtendedInfo: array[0..47] of AnsiChar);
  end;

It’s possible that Byte may be more appropriate than AnsiChar. It’s a bit hard to tell of course because C, unlike Pascal, doesn’t have separate types for Byte and AnsiChar. But these arrays look to me as though they would be read as text so my guess is that AnsiChar would be more appropriate.

Leave a Comment