Einzelnen Beitrag anzeigen

NicoDE
(Gast)

n/a Beiträge
 
#9

Re: Delphi-Equivalent zur C-union

  Alt 22. Jun 2005, 10:36
Ein C-struct entspricht einem Delphi-record; soweit dürfte das klar sein.

Nehmen wir mal die C-Union:
Code:
//...
    union
    {
        long   foo;
        char   bar;
    };
Unions werden verwendet um die gleiche Variable (Speicheradresse) mit verschiedenen Namen ansprechen zu können. '.foo' und '.bar' sind also an der gleichen Stelle (und eigentlich eine Variable). In der Variable steht entweder ein 'Foo'-Wert oder ein 'Bar'-Wert (die Unterscheidung zwischen den beiden Bedeutungen einer Variable muss irgendwo in der Dokumentation stehen...). Verwendet wird das ganze meist um Speicherplatz zu sparen.

In Delphi Language nennt man dies den 'varianten Teil einer Struktur'; und so sieht das ganze so aus:
Delphi-Quellcode:
//...
  case Integer of
    0: (
      foo: Longint;
    );
    1: (
      bar: AnsiChar;
    );
{ end; }
Integer als Aufzählungstyp ist frei gewählt. Die einzelnen Varianten der Struktur sind in Delphi-Language deutlicher zu erkennen als in C. Man muss sich nur an das 'case'-Konstrukt in Strukturen gewöhnen.

Warum ist nun das Ende des varianten Teils der Struktur auskommentiert?
Nun, die Delphi Language unterstützt variante Teile nur als letzten Teil einer Struktur. Es können also keine weiteren Variablen folgen!

Was soll man dann aber mit folgenden C-Konstrukt anstellen?
Code:
//...
    union
    {
        long   foo;
        char   bar;
    };
    int alc;
Da in der Delphi-Language keine weiteren Variablen folgen können, müssen wir die folgenden Strukturmitglieder an den größten Teil der varianten Struktur anhängen. Da .foo größer ist als .bar, müssen wir beide vertauschen. Das ganze sieht dann so aus:
Delphi-Quellcode:
//...
  case Integer of
    1: (
      bar: AnsiChar;
    );
    0: (
      foo: Longint;
{ end; }
      alc: Integer;
    );
oder anders formatiert:
Delphi-Quellcode:
//...
  case Integer of
    1: (bar: AnsiChar);
    0: (foo: Longint;
  alc: Integer);
Nun haben wir also einen Trick gefunden, um Strukturmitglieder nach einem varianten Teil zu deklarieren.


Dies kann natürlich wieder ein varianter Teil sein, also in der oben gestellten Frage:
Delphi-Quellcode:
//...
  case Integer of
    0: (
      rows : Integer;
    );
    1: (
      height: Integer;
{ end; }
      case Integer of
        0: (
          cols : Integer;
        );
        1: (
          width : Integer;
        );
    );
oder anders formatiert:
Delphi-Quellcode:
//...
  case Integer of
    0: (rows : Integer);
    1: (height: Integer;
  case Integer of
    0: (cols : Integer);
    1: (width : Integer))
  end;
(das Semikolon fehlt nach dem letzten Teil eines Blocks - Geschmacksfrage, aber gültiges Pascal)


Kommen wir am Ende zu benannten C-Unions:
Code:
//...
    union
    {
        long   foo;
        char   bar;
    } dat;
Die Variablen werden nun mit dat.foo und dat.bar angesprochen. Das entspricht der Funktionalität eines Delphi-record.
Also übersetzen wir die benannte Union mit einem inline-record:
Delphi-Quellcode:
//...
  dat: record
    case Integer of
      0: (
        foo: Longint;
      );
      1: (
        bar: AnsiChar;
      );
  { end; }
  end;

Wenn wir nun unser gewonnenes Wissen bündeln und die Macht mit uns ist, dann können wir den oben gefragten C-Code mit folgendem Übersetzen:
Delphi-Quellcode:
type
  CvMat = record
    type_: Integer;
    step: Integer;
    refcount: PInteger;
    data: record
      case Integer of
        0: (
          ptr: PByte;
        );
        1: (
          s: PSmallInt;
        );
        2: (
          i: PInteger;
        );
        3: (
          fl: PSingle;
        );
        4: (
          db: PDouble;
        );
    { end; }
    end;
    case Integer of
      0: (
        rows: Integer;
      );
      1: (
        height: Integer;
  { end; }
        case Integer of
          0: (
            cols: Integer;
          );
          1: (
            width: Integer;
          );
      { end; }
      );
  end;
oder anders formatiert:
Delphi-Quellcode:
type
  CvMat = record
    type_ : Integer;
    step : Integer;
    refcount : PInteger;
    data : record
      case Integer of
        0: (ptr : PByte);
        1: (s : PSmallInt);
        2: (i : PInteger);
        3: (fl : PSingle);
        4: (db : PDouble)
    end;
    case Integer of
      0: (rows : Integer);
      1: (height: Integer;
    case Integer of
      0: (cols : Integer);
      1: (width : Integer))
  end;
  Mit Zitat antworten Zitat