2009-07-14 10 views
2

Warum erstellt strlen() beim Kompilieren einer 64-Bit-Anwendung eine 64-Bit-Ganzzahl? Fehle ich etwas?Warum gibt strlen() eine 64-Bit-Ganzzahl zurück? Fehle ich etwas?

Ich verstehe, dass strlen() gibt eine size_type zurück, und per Definition sollte dies nicht ändern, aber ... Warum würde strlen benötigen, um eine 64-Bit-Ganzzahl zurückgeben?

Die Funktion ist für die Verwendung mit Strings vorgesehen. Mit diesem gesagt:

Entwickeln Programmierer häufig Multi-Gigabyte oder Multi-Terabyte-Strings? Wenn dies der Fall wäre, würden sie nicht einen besseren Weg brauchen, um die Stringlänge zu bestimmen, als nach einem NULL-Zeichen zu suchen?

Ich denke, das ist lächerlich, in der Tat, vielleicht brauchen wir eine StrLenAsync() -Funktion mit einem Callback, nur um den extrem langen Prozess für die Suche nach dem NULL in der 40TB-Zeichenfolge zu behandeln. Ton dumm? Ja, well strlen() gibt eine 64-Bit-Ganzzahl zurück!

Natürlich ist die vorgeschlagene StrLenAsync() - Funktion ein Witz.

+12

Woran denken Sie, dass size_t sich nicht je nach Plattform ändert? – Yacoby

+6

Zero-terminated Saiten sind sowieso dumm, also warum kümmern? ;) – OregonGhost

+6

@NTDLS: auf einer 64-Bit-Plattform gibt es keinen echten Overhead bei der Rückgabe einer 64-Bit-Ganzzahl, da sie in ein einzelnes Register passt. (Angenommen, ein Register wird für den Rückgabewert verwendet, was bei den meisten Plattformen, die ich gesehen habe, der Fall ist). –

Antwort

17

Beim Kompilieren für ein 64-Bit-Ziel wird size_t als 64-Bit definiert. Dies ist sinnvoll, da size_t für Größen aller Arten von Objekten verwendet wird, nicht nur für Strings.

+1

Völlig verstanden, aber ist das nicht viel Overhead für eine Funktion, die wahrscheinlich nie einen Rückgabewert über die maximal 32-Bit-Ganzzahl ohne Vorzeichen sehen wird? – NTDLS

+2

Für den Unterschied zwischen zwei Zeigern genau zu sein. Und Strylen ist genau das. –

+16

Das ist ein bisschen wie zu sagen, dass ein 32-Bit size_t 16 Bit Overhead hat, weil die meisten Strings deutlich unter 64k sind. :-) –

8

Bei einer 64-Bit-App ist es definitiv möglich, eine 5-GB-Zeichenfolge zu erstellen.

Die Spezifikation soll Sie nicht davon abhalten, dumme Dinge zu tun.

Auch wenn es nicht benötigt wurde, wäre es nicht wert, die Spezifikation zu ändern, anstatt eine size_t zu verwenden, nur um den Rückgabewert 4 statt 8 Bytes zu erhalten.

+2

Es ist auch möglich, in einer 32-Bit-App eine 5-GB-Zeichenfolge zu erstellen. Es kann nicht einfach in den 32-Bit-Adressraum auf einmal abgebildet werden, also müsste Strlen irgendwie clever sein, was nicht der Fall ist. Siehe den folgenden interessanten Artikel für Details: http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx – OregonGhost

+3

Die Strlen Die Funktion arbeitet mit einem Zeiger, vorausgesetzt, dass die Zeichenfolge im zusammenhängenden Speicher folgt. Ein 32-Bit-Zeiger kann keine Zeichenfolge darstellen, die größer als 4G ist (abzüglich des Speicherplatzes, den das O/S reserviert) * im Speicher *. Zwar gibt es sicherlich mehrere Möglichkeiten, Strings größer als der Adressraum darzustellen, sie sind jedoch wegen der in ihre Spezifikation eingebauten Annahmen für strlen nicht relevant. –

1

Nun, 1) size_t ist ein typedef und variiert mit Architekturen und 2) Wäre es nicht sinnvoll, die größte ganze Zahl als Rückgabewert zu haben? Warum 32 Bits? Warum nicht 16? Es ist 64 auf Ihrem Computer, weil das die maximale Stringlänge ist.

0

strlen() müssen Rückgabetyp verwenden, der die Größe des größten Objekts im Zuordnungsmodell darstellen kann.

Sie könnten std::string verwenden. Sein size_type ist gleich dem size_type des Zuweisers. Wenn Sie also Ihren eigenen Zuordner erstellen, könnte std::string::size() sogar char als Rückgabetyp verwenden.

Dank Kommentar in Kommentaren. std::string ist nur eine Spezialisierung der std::basic_string. Sicher sollten Sie std::basic_string mit benutzerdefinierten Zuordner verwenden.

+1

Sie können nicht (in Standard C++) den Zuordner für std :: string ändern: es ist ein typedef, keine Vorlage. Sie müssen basic_string verwenden. –

+0

Sicher ist es, ich war eilig. –

7

Hier ist ein Diagramm, das die Größe einiger Grundtypen in den gängigsten Datenmodellen zeigt:

  ILP32 LP64 LLP64 ILP64 
char  8  8  8  8 
short  16 16 16 16 
int  32 32 32 64 
long  32 64 32 64 
long long 64 64 64 64 
pointer 32 64 64 64 
size_t 32 64 64 64 

Das 32-Bit-Windows-Datenmodell ist ILP32 und das 64-Bit-Windows-Datenmodell ist LLP64.

+0

+1 für die große Bildansicht und eine schöne Grafik –

+0

Ich hoffte, dass es hilfreich sein könnte. Ich bin dabei, eine sehr große C++ - Codebasis auf 64-Bit zu portieren, also lebe und atme ich dieses Zeug gerade. – Nick

+0

Ja, sehr schöne Tabelle. Ich habe eine Kopie gespeichert. – NTDLS

2

Es geht nicht darum, ob jemand tatsächlich eine Schnur dieser Größe macht. Laut Konvention sind ALLE Rückgabetypen, die die Anzahl der Bytes angeben, die im Speicher belegt sind, size_t.

3

Ich kann an mehrere Anwendungen denken, wo eine Kette von 4GB einfach nicht genug ist (Computerbiologie, Computerforensik sind zwei RIESIGE).Nimm das nicht an, weil DU es nicht tust, was auch sonst niemand tut.

+0

Oh nein, das verstehe ich vollkommen. Ich sage nur, dass Sie diese 4 GB + Array von Zeichen nicht zu einer strlen() - Funktion übergeben möchten. Sie * können * besser sein, die Länge zu verfolgen, während Sie es bauen. – NTDLS

+2

Wir verwenden keine 4GB-Strings in Computerforensik. Das wäre albern. – vy32

+0

Sie haben nie eine ganze Festplatte für eine spätere Untersuchung indiziert? Wie wäre es, wenn ein Handy aus einer Szene genommen wird? Es ist einfacher, den Inhalt der SD-Karte zu indexieren, als immer wieder von der Karte zu lesen.Wenn Sie sich auf die Verwendung von strlen() beziehen, um die Länge einer 4-GB-Zeichenfolge zu finden, dann ist das ja albern. Sonst glaube ich nicht, dass ich hier dumm bin. –

Verwandte Themen