Offene Arrays

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Unterstützung für Delphi-Datentypen und Sprachkonzepte


Unterstützung für offene Arrays

Object Pascal verwendet das Konstrukt "offenes Array", das die Übergabe eines Arrays ohne festgelegte Große an eine Funktion erlaubt. Obwohl es in C++ für diesen Typ keine direkte Unterstützung gibt, kann eine Object Pascal-Funktion mit einem offenen Array-Parameter durch die explizite Übergabe zweier Parameter aufgerufen werden:

  • Einen Zeiger auf das erste Element des Arrays
  • Einen Zähler, der den Wert des letzten Index darstellt (d. h. die Größe/Anzahl der Array-Elemente minus eins)
Hinweis: Früher hatte der Zähler-Parameter das Suffix _Size, jetzt aber das Suffix _High, was _Size minus 1 entspricht.

Beispielsweise hat die Funktion Mean in math.hpp in Object Pascal und in C++ die folgenden Deklarationen:

Delphi-Deklaration:

 function  Mean(Data:  array of  Double): Double;

C++-Deklaration:

  double __fastcall Mean(double *Data, const int Data_High);

Der folgende Code zeigt den Aufruf der Funktion Mean in C++:

 double  d[] = { 3.1, 4.4, 5.6 }; 
 
 // explicitly specifying last index 
 double  x = Mean(d, 2) ; 
 
 // better: use sizeof to ensure that the correct value is passed 
 double  y = Mean(d, ( sizeof (d) /  sizeof (d[0])) - 1) ; 
 
 // use macro in sysopen.h 
 double  z = Mean(d, ARRAYSIZE(d) - 1) ;

Hinweis: In ähnlichen Fällen, in welchen die Object Pascal-Funktion aber einen var-Parameter übernimmt, sind die C++-Funktionsdeklarationsparameter nicht const.

Berechnen der Anzahl der Elemente

Wenn die Anzahl der Elemente in einem Array mit sizeof(), mit dem Makro ARRAYSIZE oder mit dem Makro EXISTINGARRAY berechnet wird, dürfen Sie keinen Zeiger auf das Array verwenden. Übergeben Sie stattdessen den Namen des Arrays.

double  d[] = { 3.1, 4.4, 5.6 } ; 
int  n = ARRAYSIZE(d); //  sizeof (d)/ sizeof (d[0]) => 24/8 =>  3 

double  *pd = d; 
int  m = ARRAYSIZE(pd); //  sizeof (pd)/ sizeof (pd[0]) => 4/8 => 0 => Error !

Die Übernahme der Größe eines Arrays (mit "sizeof") ist nicht identisch mit der Übernahme der Größe eines Zeigers (mit "sizeof"). Zum Beispiel wird bei den folgenden Deklarationen

double  d[3]; 
double  *p = d;

die Übernahme der Größe des Arrays

sizeof (d) / sizeof  d[0]

nicht in derselben Weise ausgewertet wie die Übernahme der Größe des Zeigers:

sizeof (p) / sizeof (p[0])

Dieses Beispiel und die folgenden verwenden das Makro ARRAYSIZE anstatt des Operators sizeof(). Weitere Informationen über das Makro ARRAYSIZE finden Sie in der Online-Hilfe.

Temporäre Arrays

Object Pascal unterstützt die Übergabe von unbenannten, temporären, offenen Arrays an Funktionen. In C++ gibt es dafür keine Syntax. Da Variablendefinitionen mit anderen Anweisungen gemischt werden können, kann einfach eine benannte Variable bereitgestellt werden.

Delphi:

 Result := Mean([3.1, 4.4, 5.6]);

C++ mit Verwendung einer benannten "temporären Variable":

 double  d[] = { 3.1, 4.4, 5.6 } ; 
 return  Mean(d, ARRAYSIZE(d) - 1) ;

Um den Gültigkeitsbereich der benannten "temporären Variable" zu beschränken und somit eine Kollision mit anderen lokalen Variablen zu verhindern, öffnen Sie in der Definition einen neuen Gültigkeitsbereich:

 long double  x; 
 
 { 
 double  d[] = { 4.4, 333.1, 0.0 } ; 
 x = Mean(d, ARRAYSIZE(d) - 1) ; 
 
 }

Einen weiteren Lösungsansatz bietet das Makro OPENARRAY.

array of const

Object Pascal unterstützt das Sprachkonstrukt "array of const". Dieser Argumenttyp entspricht der Übernahme eines offenen TVarRec-Arrays per Wert.

Das folgende Object Pascal-Codesegment ist so deklariert, dass ein "array of const" akzeptiert wird:

function  Format( const  Format:  string ; Args:  array of const ):  string ;

In C++ lautet der Prototyp:

UnicodeString  __fastcall  Format( const  UnicodeString Format , 
TVarRec  const  *Args,  const int  Args_Size) ;

Die Funktion wird genau wie jede andere Funktion, die ein offenes Array übernimmt, aufgerufen:

void show_error ( int  error_code, UnicodeString  const  &error_msg) 
{ 
  TVarRec v[] = { error_code, error_msg } ; 
  ShowMessage(Format("%d: %s", v, ARRAYSIZE(v) - 1)) ; 
}

Das Makro OPENARRAY

Das in sysopen.h definierte Makro OPENARRAY stellt eine Alternative zur Verwendung einer benannten Variable für die Übergabe eines temporären, offenen Arrays an eine Funktion dar, die ein offenes Array per Wert übernimmt.

Das Makro wird folgendermaßen verwendet:

OPENARRAY(T, (value1, value2, value3)) // up to 19 values

T ist der Typ des zu erstellenden offenen Arrays, und mit den value-Parametern wird das Array gefüllt. Die Klammern um die value-Argumente sind erforderlich. Zum Beispiel:

void  show_error(int  error_code, UnicodeString  const  &error_msg) 
{
  ShowMessage(Format("%d: %s", OPENARRAY(TVarRec, (error_code, error_msg)))); 
}

Mit dem Makro OPENARRAY können bis zu 19 Werte übergeben werden. Wenn ein größeres Array erforderlich ist, muss eine explizite Variable definiert werden. Die Verwendung des Makros OPENARRAY bedingt eine (geringe) Laufzeiteinbuße, weil das zugrunde liegende Array zugewiesen und jeder Wert zusätzlich kopiert werden muss.

Codebeispiele

Das Makro EXISTINGARRAY

Das in sysopen.h definierte Makro EXISTINGARRAY kann zum Übergeben eines vorhandenen Arrays verwendet werden, wenn ein offenes Array erwartet wird.

Das Makro wird folgendermaßen verwendet:

 long double  Mean( const double  *Data,  const int  Data_Size) ; 
 double  d[] = { 3.1, 3.14159, 2.17128 } ; 
 Mean(EXISTINGARRAY (d)) ;

Hinweis: Der Abschnitt Berechnen der Anzahl der Elemente bezieht sich auch auf das Makro EXISTINGARRAY.

C++-Funktionen, die offene Array-Argumente übernehmen

Beim Schreiben einer C++-Funktion, die an ein offenes Array aus Object Pascal übergeben werden soll, muss unbedingt explizit die "Übergabe-per-Wert"-Semantik beibehalten werden. Insbesondere, wenn die Deklaration für die Funktion der "Übergabe per Wert" entspricht, müssen Sie alle Elemente explizit kopieren, bevor Sie sie modifizieren. In Object Pascal ist ein offenes Array ein integrierter Typ und kann per Wert übergeben werden. In C++ ist der Typ "offenes Array" mithilfe eines Zeigers implementiert, der das Original-Array ändert, wenn keine lokale Kopie davon erstellt wird.

Object Pascal-Funktionen, die Arrays zurückgeben

Object Pascal ermöglicht, dass Funktionen Arrays zurückzugeben, was in C++ nicht durchgeführt werden kann. Um diesen Unterschied aufzulösen, werden von Object Pascal-Methoden, die Arrays zurückgeben (wie z. B. T[1..n]), Prototypen erstellt, die eine Instanz von StaticArray<T, n> zurückgeben.

Siehe auch