So sehr ich C und C ++ liebe, ich kann nicht anders, als mir bei der Auswahl der nullterminierten Zeichenfolgen den Kopf zu kratzen:
- Vor C existierende Zeichenfolgen mit Längenpräfix (dh Pascal)
- Zeichenfolgen mit Längenpräfix beschleunigen mehrere Algorithmen, indem sie eine Suche mit konstanter Zeitlänge ermöglichen.
- Zeichenfolgen mit Längenpräfix machen es schwieriger, Pufferüberlauffehler zu verursachen.
- Selbst auf einem 32-Bit-Computer ist eine Zeichenfolge mit Präfixlänge nur drei Byte breiter als eine Zeichenfolge mit Nullterminierung, wenn Sie zulassen, dass die Zeichenfolge die Größe des verfügbaren Speichers hat. Auf 16-Bit-Computern ist dies ein einzelnes Byte. Auf 64-Bit-Computern sind 4 GB eine angemessene Beschränkung der Zeichenfolgenlänge. Selbst wenn Sie es auf die Größe des Maschinenworts erweitern möchten, verfügen 64-Bit-Computer normalerweise über ausreichend Speicher, sodass die zusätzlichen sieben Bytes eine Art Nullargument darstellen. Ich weiß, dass der ursprüngliche C-Standard für wahnsinnig schlechte Maschinen (in Bezug auf den Speicher) geschrieben wurde, aber das Argument der Effizienz verkauft mich hier nicht.
- Nahezu jede andere Sprache (z. B. Perl, Pascal, Python, Java, C # usw.) verwendet Zeichenfolgen mit Längenpräfix. Diese Sprachen schlagen normalerweise C in Benchmarks zur Manipulation von Zeichenfolgen, da sie mit Zeichenfolgen effizienter sind.
- C ++ hat dies mit dem etwas korrigiert
std::basic_string
Vorlage , aber einfache Zeichenarrays, die nullterminierte Zeichenfolgen erwarten, sind immer noch weit verbreitet. Dies ist auch nicht perfekt, da eine Heap-Zuweisung erforderlich ist. - Null-terminierte Zeichenfolgen müssen ein Zeichen (nämlich null) reservieren, das in der Zeichenfolge nicht vorhanden sein kann, während Zeichenfolgen mit Längenpräfix eingebettete Nullen enthalten können.
Einige dieser Dinge sind in jüngerer Zeit ans Licht gekommen als C, daher wäre es sinnvoll, wenn C nichts von ihnen gewusst hätte. Einige waren jedoch deutlich, lange bevor C entstand. Warum wurden nullterminierte Zeichenfolgen anstelle des offensichtlich überlegenen Längenpräfixes gewählt?
BEARBEITEN : Da einige nach Fakten gefragt haben (und die, die ich bereits zur Verfügung gestellt habe) zu meinem Effizienzpunkt oben nicht mochten, sind sie auf einige Dinge zurückzuführen:
- Concat mit nullterminierten Zeichenfolgen erfordert eine zeitliche Komplexität von O (n + m). Längenpräfixe erfordern oft nur O (m).
- Die Länge mit nullterminierten Zeichenfolgen erfordert eine Komplexität von O (n). Das Längenpräfix ist O (1).
- Länge und Concat sind bei weitem die häufigsten Zeichenfolgenoperationen. Es gibt mehrere Fälle, in denen nullterminierte Zeichenfolgen effizienter sein können, diese treten jedoch viel seltener auf.
In den folgenden Antworten sind einige Fälle aufgeführt, in denen nullterminierte Zeichenfolgen effizienter sind:
- Wenn Sie den Anfang eines Strings abschneiden und an eine Methode übergeben müssen. Sie können dies nicht wirklich in konstanter Zeit mit Längenpräfix tun, selbst wenn Sie die ursprüngliche Zeichenfolge zerstören dürfen, da das Längenpräfix wahrscheinlich den Ausrichtungsregeln entsprechen muss.
- In einigen Fällen, in denen Sie die Zeichenfolge nur zeichenweise durchlaufen, können Sie möglicherweise ein CPU-Register speichern. Beachten Sie, dass dies nur funktioniert, wenn Sie die Zeichenfolge nicht dynamisch zugewiesen haben (da Sie sie dann freigeben müssten und das gespeicherte CPU-Register verwenden müssten, um den Zeiger zu speichern, den Sie ursprünglich von malloc und Freunden erhalten haben).
Keines der oben genannten ist fast so häufig wie Länge und Concat.
In den folgenden Antworten wird noch eines behauptet:
- Sie müssen das Ende der Zeichenfolge abschneiden
Dies ist jedoch falsch - es ist dieselbe Zeitspanne für nullterminierte und längenpräfixierte Zeichenfolgen. (Nullterminierte Zeichenfolgen setzen einfach eine Null an die Stelle, an der das neue Ende sein soll. Längenpräfixe werden nur vom Präfix subtrahiert.)