String-Typen (Delphi)

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Datentypen, Variablen und Konstanten - Index


In diesem Thema werden die in der Sprache Delphi verfügbaren String-Datentypen beschrieben. Folgende Typen werden behandelt:

Allgemeines zu String-Typen

Ein String repräsentiert eine Zeichenfolge. Delphi unterstützt die folgenden vordefinierten String-Typen.

String-Typen

Typ Maximale Länge Erforderlicher Speicherplatz Verwendungszweck

ShortString

255 Zeichen

2 bis 256 Byte

Abwärtskompatibilität.

AnsiString

~2^31 Zeichen

4 Byte bis 2 GB

8-Bit-Zeichen (ANSI), DBCS ANSI, MBCS ANSI, Unicode-Zeichen usw.

UnicodeString

Hinweis: In RAD Studio ist string ein Alias für UnicodeString.

~2^30 Zeichen

4 Byte bis 2 GB

Unicode-Zeichen, 8-Bit-Zeichen (ANSI), Mehrbenutzersystem-Server und mehrsprachige Anwendungen

UnicodeString ist der Standard-String-Typ.

WideString

~2^30 Zeichen

4 Byte bis 2 GB

Unicode-Zeichen, Mehrbenutzersystem-Server und mehrsprachige Anwendungen. WideString wird nicht von den Delphi-Compilern für mobile Plattformen unterstützt, sondern nur von den Delphi-Compilern für Desktop-Plattformen. Sie sollten UnicodeString anstelle von WideString verwenden.

Hinweis: Der Standardtyp für Strings ist UnicodeString. WideString wird aus Kompatibilitätsgründen mit dem COM-Typ BSTR bereitgestellt. Für Nicht-COM-Anwendungen sollten Sie stets UnicodeString verwenden. Für die meisten Zwecke ist der Typ UnicodeString am besten geeignet. Der Typ string ist ein Alias für UnicodeString.

String-Typen können in Zuweisungen und Ausdrücken miteinander kombiniert werden. Der Compiler führt die erforderlichen Umwandlungen automatisch durch. Strings, die per Referenz an eine Funktion oder Prozedur übergeben werden (z.B. als var- und out-Parameter), müssen jedoch den korrekten Typ aufweisen. Strings können explizit in einen anderen String-Typ umgewandelt werden. Die Umwandlung eines Multibyte-Strings in einen Einzelbyte-String kann jedoch zu Datenverlust führen.

Im Folgenden werden einige spezielle String-Typen erläutert:

  • Codeseitenabhängige AnsiString-Typen werden folgendermaßen definiert:
Type mystring = type AnsiString(CODEPAGE)
Hierbei handelt es sich um einen AnsiString, der seine internen Daten in einer bestimmen Codeseite beibehält.
  • Der Typ RawByteString ist type AnsiString($FFFF). RawByteString ermöglicht die Übergabe von String-Daten jeder beliebigen Codeseite, ohne dass Codeseitenkonvertierungen vorgenommen werden müssen. RawByteString sollte nur als const- oder Wertetypparameter oder als Rückgabetyp einer Funktion verwendet werden. Er sollte nie per Referenz (mit var) übergeben und nie als Variable instantiiert werden.
  • UTF8String repräsentiert einen String, der in UTF-8 (variable Anzahl von Bytes, Unicode) codiert ist. Es handelt sich dabei um einen codeseitenabhängigen AnsiString-Typ mit einer UTF-8-Codeseite.

Das reservierte Wort string fungiert wie ein generischer Typbezeichner. Zum Beispiel:

var S: string;

Hier wird die Variable S für einen String erstellt. Auf der Win32-Plattform interpretiert der Compiler string als UnicodeString (wenn danach keine Zahl in eckigen Klammern folgt).

Auf der Win32-Plattform können Sie mit der Direktive {$H-}string in ShortString umwandeln. Dieses Vorgehen ist möglicherweise bei der Verwendung von älterem 16-Bit-Delphi-Code oder Turbo-Pascal-Code mit aktuellen Programmen hilfreich.

Bitte beachten Sie, dass das Schlüsselwort string auch für die Deklaration von ShortString-Typen mit einer bestimmten Länge verwendet wird (siehe Kurze String-Typen weiter unten).

Der Vergleich von Strings wird durch die Wertigkeit der Elemente an den entsprechenden Positionen definiert. Bei Vergleichen von Strings unterschiedlicher Länge wird jedes Zeichen im längeren String, dem kein Zeichen im kürzeren String entspricht, als "größer" angesehen. So ist beispielsweise "AB" größer als "A". Dies bedeutet, dass "AB" > "A" True zurückgibt. Strings mit der Länge null repräsentieren die niedrigsten Werte.

Sie können eine String-Variable wie ein Array indizieren. Wenn S keine UnicodeString-String-Variable und i ein Integer-Ausdruck ist, repräsentiert S[i] das i-te Byte in S, das nicht das i-te Zeichen oder überhaupt ein vollständiges Zeichen für einen Multibyte-String (MBCS) sein muss. Ebenso kann das Indizieren einer UnicodeString-Variable ein Element ergeben, dass kein vollständiges Zeichen ist. Wenn der String Zeichen aus dem Basic Multilingual Plane (BMP) enthält, sind alle Zeichen 2 Byte groß, daher ergibt die Indizierung des Strings Zeichen. Falls aber einige Zeichen nicht im BMP enthalten sind, kann ein indiziertes Element ein Surrogatpaar – kein vollständiges Zeichen – sein.

Die Standardfunktion Length gibt die Anzahl der Elemente in einem String zurück. Wie oben bereits erwähnt, muss die Anzahl der Elemente nicht notwendigerweise gleich der Anzahl der Zeichen sein. Mit der Prozedur SetLength wird die Länge eines Strings festgelegt. Die Funktion SizeOf gibt die Anzahl der Bytes zurück, die zur Darstellung einer Variable oder eines Typs verwendet wird. SizeOf gibt die Anzahl der Zeichen in einem String nur für kurze Strings zurück. SizeOf gibt für alle anderen String-Typen die Anzahl der Bytes in einem Zeiger zurück, weil es sich bei diesen Strings um Zeiger handelt.

Bei einem kurzen String oder einem AnsiString hat S[i] den Typ AnsiChar. Bei einem WideString hat S[i] den Typ WideChar. Für Einzelbyte-Gebietsschemas (Western) weist die Anweisung MyString[2] := 'A'; dem zweiten Zeichen von MyString den Wert A zu. Im folgenden Quelltext wird MyString mit der Standardfunktion UpCase in Großbuchstaben umgewandelt:

var I: Integer;
begin
  I := Length(MyString);
  while I > 0 do
  begin
    MyString[I] := UpCase(MyString[I]);
    I := I - 1;
  end;
end;

Wenn Sie Strings auf diese Weise indizieren, müssen Sie darauf achten, dass Sie nicht über das Ende des Strings hinaus indizieren, da dies zu einer Zugriffsverletzung führen würde. Außerdem sollten Sie Indizes für Strings nicht als var-Parameter übergeben, da dies ineffizienten Code ergibt.

Sie können den Wert einer String-Konstante – oder eines anderen Ausdrucks, der einen String zurückgibt – einer Variable zuweisen. Die Länge des Strings ändert sich bei der Zuweisung dynamisch. Beispiele:

MyString := 'Hello world!';
MyString := 'Hello' + 'world';
MyString := MyString + '!';
MyString := ' '; { space }
MyString := '';  { empty string }

Kurze String-Typen

Ein ShortString hat eine Länge von 0 bis 255 Einzelbyte-Zeichen. Obwohl sich die Länge eines ShortString dynamisch ändern kann, beträgt die statische Speicherplatzzuweisung immer 256 Byte. Im ersten Byte wird die Länge des Strings gespeichert, die restlichen 255 Byte stehen für die Zeichen zur Verfügung. Wenn S eine ShortString-Variable ist, gibt Ord(S[0]), wie Length(S), die Länge von S zurück; durch Zuweisen eines Wertes an S[0], wie mit SetLength, wird die Länge von S geändert. ShortString ist nur aus Gründen der Abwärtskompatibilität vorhanden.

Delphi unterstützt kurze String-Typen (Untertypen von ShortString), deren maximale Länge zwischen 0 und 255 Zeichen liegt. Diese Typen werden mit einer Zahl in eckigen Klammern dargestellt, die auf das reservierte Wort string folgt. Zum Beispiel:

var MyString: string[100];

Hier wird die Variable MyString mit einer maximalen Länge von 100 Zeichen erstellt. Dies entspricht den folgenden Deklarationen:

type CString = string[100];
var MyString: CString;

Bei Variablen, die auf diese Weise deklariert werden, wird dem Typ nur so viel Speicherplatz zugewiesen, wie für die angegebene Länge plus ein Byte erforderlich ist. In diesem Beispiel belegt MyString 101 Byte. Für eine Variable des vordefinierten Typs ShortString wären dagegen 256 Byte erforderlich.

Bei einer Wertzuweisung an eine kurze String-Variable wird der String abgeschnitten, wenn die maximale Länge für den Typ überschritten wird.

Die Standardfunktionen High und Low arbeiten mit Variablen und Typbezeichnern für kurze Strings. High gibt die maximale Länge des kurzen String-Typs und Low gibt null zurück.

AnsiString

AnsiString repräsentiert einen dynamisch zugewiesenen String, dessen maximale Länge nur durch den verfügbaren Speicherplatz begrenzt wird.

Eine AnsiString-Variable ist eine Struktur, die String-Informationen enthält. Wenn die Variable leer ist (also einen String der Länge null enthält), hat der Zeiger den Wert nil, und der String belegt keinen zusätzlichen Speicherplatz. Ist die Variable nicht leer, zeigt sie auf einen dynamisch zugewiesenen Speicherblock, der einen String-Wert enthält. Dieser Speicherplatz wird auf dem Heap reserviert, aber er wird vollkommen automatisch verwaltet und erfordert keinerlei Benutzercode. Die Struktur AnsiString enthält einen Längenindikator (32 Bit), eine Referenzzählung (32 Bit), eine Datenlänge (16 Bit), die die Anzahl der Bytes pro Zeichen angibt, und eine Codeseite (16 Bit).

Ein AnsiString repräsentiert einen Einzelbyte-String. Bei einem Einzelbyte-Zeichensatz (SBCS = Single-Byte Character Set) repräsentiert jedes Byte eines Strings ein Zeichen. In einem Multibyte-Zeichensatz (MBCS = Multi-Byte Character Set) sind die Elemente weiterhin Einzelbytes, aber einige Zeichen werden mit einem einzelnen Byte und andere mit mehreren Bytes dargestellt. Multibyte-Zeichensätze, insbesondere Doppelbyte-Zeichensätze (DBCS = Double-Byte Character Set), werden in erster Linie für asiatische Sprachen verwendet. Ein AnsiString kann MBCS-Zeichen enthalten.

Die Indizierung von AnsiString beginnt mit 1. Eine zuverlässige Indizierung von Multibyte-Strings ist nicht möglich, da S[i] das i-te Byte (und nicht notwendigerweise das i-te Zeichen) in S darstellt. Das i-te Byte kann ein einzelnes Zeichen oder Teil eines Zeichens sein. Jedoch gibt es für alle Standardfunktionen zur AnsiString-Verarbeitung multibytefähige Entsprechungen, die auch die Besonderheiten länderspezifischer Zeichensätze berücksichtigen. (Die Namen von Multibyte-Funktionen beginnen normalerweise mit Ansi. Beispielsweise hat die Multibyte-Version von StrPos den Namen AnsiStrPos.) Die Unterstützung von Multibyte-Zeichen ist betriebssystemabhängig und basiert auf dem verwendeten Gebietsschema.

Da AnsiString-Variablen Zeiger haben, können zwei oder mehrere dieser Variablen auf denselben Wert zeigen, ohne zusätzlichen Speicherplatz zu belegen. Der Compiler nützt dies zur Einsparung von Ressourcen. Auch Zuweisungen werden schneller ausgeführt. Sobald eine AnsiString-Variable freigegeben oder mit einem neuen Wert belegt wird, wird der Referenzzähler des alten AnsiString (d.h. des vorhergehenden Wertes der Variable) dekrementiert und der Referenzzähler des neuen Wertes (falls ein solcher zugewiesen wurde) inkrementiert. Erreicht der Referenzzähler eines Strings den Wert null, wird der belegte Speicherplatz freigegeben. Dieser Vorgang wird als Referenzzählung bezeichnet. Wenn der Wert eines einzelnen Zeichens im String über einen Index geändert werden soll, wird eine Kopie des Strings angelegt. Dies ist aber nur möglich, wenn der betreffende Referenzzähler größer als 1 ist. Diesen Vorgang nennt man "Copy-on-Write"-Semantik.

UnicodeString (der Standard-String-Typ)

Der Typ UnicodeString ist der Standard-String-Typ und repräsentiert einen dynamisch zugewiesenen Unicode-String, dessen maximale Länge nur durch den verfügbaren Speicherplatz begrenzt wird.

In einem Unicode-Zeichensatz wird jedes Zeichen durch ein oder zwei Byte repräsentiert. Unicode verfügt über mehrere Formate zur Unicode-Umwandlung, die verschiedene aber äquivalente Zeichencodierungen verwenden, die schnell ineinander umgewandelt werden können.

  • In UTF-8 können Zeichen beispielsweise von 1 bis 4 Byte groß sein. In UTF-8 entsprechen die ersten 128 Unicode-Zeichen den US-ASCII-Zeichen.
  • UTF-16 ist eine weitere häufig verwendete Unicode-Codierung, in der Zeichen entweder 2 oder 4 Byte groß sind. Die Mehrzahl der weltweit verwendeten Schriftzeichen befindet sich im Basic Multilingual Plane und kann mit 2 Byte dargestellt werden. Die übrigen Zeichen benötigen zwei 2-Byte-Zeichen, die Surrogatpaare genannt werden.
  • UTF-32 stellt jedes Zeichen mit 4 Byte dar.

Die Win32-Plattform unterstützt Einzelbyte- und Multibyte-Zeichensätze sowie den Unicode-Zeichensatz. Windows unterstützt UTF-16.

Weitere Informationen finden Sie unter Unicode Standard.

Der Typ UnicodeString hat genau dieselbe Struktur wie der Typ AnsiString. UnicodeString-Daten werden in UTF-16 codiert.

Weil UnicodeString und AnsiString die gleiche Struktur haben, arbeiten sie auch sehr ähnlich. Wenn eine UnicodeString-Variable leer ist, benötigt sie keinen zusätzlichen Speicherplatz. Wenn sie nicht leer ist, zeigt sie auf einen dynamisch zugewiesenen Speicherblock, der den String-Wert enthält. Die Speicherbehandlung dafür ist für den Benutzer ersichtlich. UnicodeString-Variablen verfügen über Referenzzähler, und zwei oder mehrere dieser Variablen können denselben Wert referenzieren, ohne zusätzlichen Speicherplatz zu belegen.

Instanzen von UnicodeString können Zeichen indizieren. Die Indizierung beginnt genau wie bei AnsiString mit 1.

UnicodeString ist zu allen anderen String-Typen zuweisungskompatibel. Zuweisungen zwischen AnsiString und UnicodeString führen aber die entsprechende Auf- oder Abkonvertierung durch. Eine Zuweisung eines UnicodeString-Typs zu einem AnsiString-Typ wird nicht empfohlen und kann zu Datenverlusten führen.

Delphi kann Unicode-Zeichen und -Strings auch durch die Typen WideChar, PWideChar und WideString unterstützen.

Weitere Informationen über die Verwendung von Unicode finden Sie in den Themen Unicode in RAD Studio und Anwendungen für Unicode anpassen.

WideString

Der Typ WideString repräsentiert einen dynamisch zugewiesenen String mit 16-Bit-Unicode-Zeichen. In einigen Punkten entspricht er mit dem Typ AnsiString. In Win32 ist der Typ WideString kompatibel mit dem COM-Typ BSTR.

WideString ist für COM-Anwendungen geeignet. WideString verfügt aber über keinen Referenzzähler, deshalb ist UnicodeString für andere Anwendungstypen flexibler und effizienter.

Eine zuverlässige Indizierung von WideString-Multibyte-Strings ist nicht möglich, da S[i] das i-te Element (und nicht notwendigerweise das i-te Zeichen) in S repräsentiert.

Die Typen Char und PChar sind in Delphi WideChar- bzw. PWideChar-Typen.

Hinweis: WideString wird nicht von den Delphi-Compilern für mobile Plattformen unterstützt, sondern nur von den Delphi-Compilern für Desktop-Plattformen.

Nullterminierte Strings

In vielen Programmiersprachen, z.B. in C und C++, fehlt ein spezieller String-Datentyp. Diese Sprachen und die mit ihnen programmierten Umgebungen verwenden sogenannte nullterminierte Strings. Ein nullterminierter String ist ein Zeichen-Array, dessen Index bei 0 beginnt und das mit NULL (#0) endet. Da das Array keine Längenangabe hat, wird das Ende des Strings durch das erste NULL-Zeichen markiert. Die Verarbeitung nullterminierter Strings erfolgt in Delphi mithilfe von Routinen, die sich in der Unit SysUtils befinden (siehe Standardroutinen und Eingabe-Ausgabe). Dies ist beispielsweise erforderlich, wenn Sie Daten gemeinsam mit Systemen nutzen, die nullterminierte Strings verwenden.

Hier einige Beispiele für die Deklaration von Typen, die nullterminierte Strings speichern können:

type
  TIdentifier = array[0..15] of Char;
  TFileName = array[0..259] of Char;
  TMemoText = array[0..1023] of WideChar;

Wenn die erweiterte Syntax aktiviert ist ({$X+}), können Sie einem statisch zugewiesenen, nullbasierten Zeichen-Array eine String-Konstante zuweisen. (Bei einem dynamischen Array ist dies nicht möglich.) Wenn Sie eine Array-Konstante mit einem String initialisieren, der kürzer als die deklarierte Länge des Arrays ist, werden die verbleibenden Zeichen auf #0 gesetzt.

Zeiger, Arrays und String-Konstanten

Bei der Bearbeitung von nullterminierten Strings werden oft Zeiger benötigt. (Siehe Zeiger und Zeigertypen (Delphi).) String-Konstanten sind zuweisungskompatibel zu den Typen PChar und PWideChar, die Zeiger auf nullterminierte Arrays mit Char und WideChar-Werten darstellen. Zum Beispiel:

var P: PChar;
  ...
P := 'Hello world!'

P zeigt auf einen Speicherbereich, der den ursprünglichen Konstanten-String "Hello world!" enthält. Das ist gleichbedeutend mit:

const TempString: array[0..12] of Char = 'Hello world!';
var P: PChar;
   ...
P := @TempString[0];

Sie können String-Konstanten auch an Funktionen übergeben, die Wert- oder const-Parameter des Typs PChar oder PWideChar akzeptieren, z.B. StrUpper('Hello world!'). Der Compiler erzeugt (wie bei Zuweisungen an PChar) eine nullterminierte Kopie des Strings und übergibt der Funktion einen Zeiger auf diese Kopie. Außerdem können Sie PChar- oder PWideChar-Konstanten einzeln oder in strukturierten Typen mit String-Literalen initialisieren. Beispiele:

const
  Message: PChar = 'Program terminated';
  Prompt: PChar = 'Enter values: ';
  Digits: array[0..9] of PChar =
    ('Zero', 'One', 'Two', 'Three', 'Four', 'Five',
     'Six', 'Seven', 'Eight', 'Nine');

Zeichen-Arrays, deren Index bei 0 beginnt, sind mit PChar und PWideChar kompatibel. Wenn Sie anstelle eines Zeigerwertes ein Zeichen-Array verwenden, wandelt der Compiler das Array in eine Zeiger-Konstante um, deren Wert der Adresse des ersten Elements im Array entspricht. Zum Beispiel:

var
  MyArray: array[0..32] of Char;
  MyPointer: PChar;
begin
  MyArray := 'Hello';
  MyPointer := MyArray;
  SomeProcedure(MyArray);
  SomeProcedure(MyPointer);
end;

Dieser Code ruft SomeProcedure zweimal mit demselben Wert auf.

Ein Zeichenzeiger kann wie ein Array indiziert werden. Im obigen Beispiel gibt MyPointer[0] den Wert H zurück. Der Index legt einen Offset fest, der zu dem Zeiger vor der Dereferenzierung addiert wird. (Bei PWideChar-Variablen wird der Index automatisch mit zwei multipliziert.) Wenn es sich bei P um einen Zeichenzeiger handelt, ist P[0] identisch mit P^ und bezeichnet das erste Zeichen im Array, P[1] das zweite Zeichen usw.; P[-1] bezeichnet das "Zeichen", das sich unmittelbar links von P[0] befindet. Der Compiler führt für diese Indizes aber keine Bereichsprüfung durch.

Das folgende Beispiel zeigt, wie mit der Funktion StrUpper anhand der Zeigerindizierung ein nullterminierter String durchlaufen wird:

function StrUpper(Dest, Source: PChar; MaxLen: Integer): PChar;
var
  I: Integer;
begin
  I := 0;
  while (I < MaxLen) and (Source[I] <> #0) do
  begin
    Dest[I] := UpCase(Source[I]);
    Inc(I);
  end;
  Dest[I] := #0;
  Result := Dest;
end;

Kombinieren von Delphi-Strings und nullterminierten Strings

Strings (AnsiString- und UnicodeString-Werte) und nullterminierte Strings (PChar-Werte) lassen sich in Ausdrücken und Zuweisungen kombinieren. Außerdem können PChar-Werte an Funktionen und Prozeduren übergeben werden, die String-Parameter akzeptieren. Die Zuweisung S := P, in der S eine String-Variable und P ein PChar-Ausdruck ist, kopiert einen nullterminierten String in einen String.

Wenn in einer binären Operation der eine Operand ein String und der andere ein PChar-Operand ist, wird der PChar-Operand in einen UnicodeString umgewandelt.

Sie können einen PChar-Wert in einen UnicodeString umwandeln. Dies ist hilfreich, wenn eine String-Operation für zwei PChar-Werte durchgeführt werden soll. Zum Beispiel:

S := string(P1) + string(P2);

Sie können einen UnicodeString- oder AnsiString-String auch in einen nullterminierten String umwandeln. Dafür gelten die folgenden Regeln:

  • Wenn S ein UnicodeString ist, wandelt PChar(S)S in einen nullterminierten String um. Das Ergebnis ist ein Zeiger auf das erste Zeichen in S. Solche Typumwandlungen werden für die Windows-API verwendet. Wenn es sich beispielsweise bei Str1 und Str2 um UnicodeString-Strings handelt, können Sie die Win32-API-Funktion MessageBox folgendermaßen aufrufen:
    MessageBox(0, PChar(Str1), PChar(Str2), MB_OK);
Verwenden Sie PAnsiChar(S), wenn S ein AnsiString ist.
  • Außerdem haben Sie die Möglichkeit, mit Pointer(S) einen String in einen untypisierten Zeiger umzuwandeln. Wenn S aber leer ist, ergibt die Umwandlung nil.
  • PChar(S) gibt stets einen Zeiger auf einen Speicherblock zurück. Wenn S leer ist, wird ein Zeiger auf #0 zurückgegeben.
  • Wenn Sie eine UnicodeString- oder AnsiString-Variable in einen Zeiger konvertieren, bleibt dieser gültig, bis die Variable den Gültigkeitsbereich verlässt oder ihr ein neuer Wert zugewiesen wird. Wenn Sie einen beliebigen anderen String-Ausdruck in einen Zeiger umwandeln, ist der Zeiger nur innerhalb der Anweisung gültig, in der die Typumwandlung durchgeführt wird.
  • Nach der Konvertierung eines UnicodeString- oder AnsiString-Ausdrucks in einen Zeiger wird der Zeiger normalerweise als schreibgeschützt ansehen. Der String kann mit dem Zeiger nur dann gefahrlos geändert werden, wenn folgende Bedingungen erfüllt sind:
    • Die Ausdruck, der umgewandelt werden soll, ist eine UnicodeString- oder AnsiString-Variable.
    • Der String ist nicht leer.
    • Der String ist eindeutig, d.h. der Referenzzähler hat den Wert 1. Um sicherzustellen, dass der String eindeutig ist, rufen Sie eine der Prozeduren SetLength, SetString oder UniqueString auf.
    • Der String wurde seit der letzten Typumwandlung nicht geändert.
    • Die zu ändernden Zeichen befinden sich alle innerhalb des Strings. Für den Zeiger darf auf keinen Fall ein Index verwendet werden, der außerhalb des Bereichs liegt.

Diese Regeln gelten auch, wenn Sie WideString-Werte mit PWideChar-Werten kombinieren.

Siehe auch