Offene Arrays
Nach oben zu Unterstützung für Object Pascal-Datentypen und Sprachkonzepte
Inhaltsverzeichnis
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.
- Hinweis: Früher hatte der Zähler-Parameter das Suffix
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:
float __fastcall Mean( float 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
long double x = Mean(d, 2) ;
// better: use sizeof to ensure that the correct value is passed
long double y = Mean(d, ( sizeof (d) / sizeof (d[0])) - 1) ;
// use macro in sysopen.h
long 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.