Antworten:
Der size_t
Typ ist der vorzeichenlose Integer-Typ, der das Ergebnis des sizeof
Operators (und des offsetof
Operators) ist. Er ist also garantiert groß genug, um die Größe des größten Objekts aufzunehmen, das Ihr System verarbeiten kann (z. B. ein statisches Array von 8 GB).
Der size_t
Typ kann größer, gleich oder kleiner als ein sein unsigned int
, und Ihr Compiler kann zur Optimierung Annahmen darüber treffen.
Genauere Informationen finden Sie im C99-Standard, Abschnitt 7.17, dessen Entwurf im PDF- Format im Internet verfügbar ist , oder im C11-Standard, Abschnitt 7.19, der auch als PDF-Entwurf verfügbar ist .
size_t
kann! Wenn nicht, wer dann?
Classic C (der frühe Dialekt von C, beschrieben von Brian Kernighan und Dennis Ritchie in The C Programming Language, Prentice-Hall, 1978) lieferte dies nicht size_t
. Das C-Standardkomitee wurde eingeführt size_t
, um ein Portabilitätsproblem zu beseitigen
Ausführlich erklärt bei embedded.com (mit einem sehr guten Beispiel)
Kurz gesagt, size_t
ist niemals negativ und maximiert die Leistung, da es sich um einen vorzeichenlosen Integer-Typ handelt, der groß genug - aber nicht zu groß - ist, um die Größe des größtmöglichen Objekts auf der Zielplattform darzustellen.
Größen sollten niemals negativ sein und sind in der Tat size_t
ein vorzeichenloser Typ. Da size_t
es kein Vorzeichen gibt, können Sie auch Zahlen speichern, die ungefähr doppelt so groß sind wie der entsprechende vorzeichenbehaftete Typ, da wir das Vorzeichenbit verwenden können, um die Größe darzustellen, wie alle anderen Bits in der vorzeichenlosen Ganzzahl. Wenn wir noch ein Bit gewinnen, multiplizieren wir den Bereich der Zahlen, den wir darstellen können, mit einem Faktor von ungefähr zwei.
Sie fragen sich also, warum nicht einfach eine verwenden unsigned int
? Es ist möglicherweise nicht in der Lage, ausreichend große Zahlen zu halten. In einer Implementierung mit unsigned int
32 Bit kann die größte Zahl dargestellt werden 4294967295
. Einige Prozessoren, wie z. B. IP16L32, können Objekte kopieren, die größer als 4294967295
Bytes sind.
Also, fragen Sie, warum nicht eine verwenden unsigned long int
? Auf einigen Plattformen ist eine Leistungsbeeinträchtigung erforderlich. Standard C erfordert, dass ein long
mindestens 32 Bit belegt. Eine IP16L32-Plattform implementiert jede 32-Bit-Länge als ein Paar von 16-Bit-Wörtern. Fast alle 32-Bit-Operatoren auf diesen Plattformen benötigen zwei Anweisungen, wenn nicht mehr, da sie mit den 32-Bit-Operatoren in zwei 16-Bit-Blöcken arbeiten. Zum Beispiel erfordert das Verschieben eines 32-Bit-Longs normalerweise zwei Maschinenbefehle - einen zum Verschieben jedes 16-Bit-Chunks.
Durch size_t
die Verwendung wird diese Leistungsbelastung vermieden. In diesem fantastischen Artikel heißt es: "Type size_t
ist ein Typedef, der ein Alias für einen vorzeichenlosen Integer-Typ ist, normalerweise unsigned int
oder unsigned long
aber möglicherweise sogar unsigned long long
. Jede Standard C-Implementierung soll die vorzeichenlose Ganzzahl auswählen, die groß genug ist - aber nicht größer als erforderlich - um die Größe des größtmöglichen Objekts auf der Zielplattform darzustellen. "
unsigned int
Dose dargestellt werden kann und von System zu System unterschiedlich ist. Es muss mindestens so sein 65536
, aber es ist üblich 4294967295
und kann 18446744073709551615
auf einigen Systemen (2 ** 64-1) sein.
unsigned char
) entfernt haben. Der Standard scheint nirgendwo die Zeichenfolge '65535' oder '65536' zu enthalten, und '+32767' kommt nur in einer Note als mögliche größte Ganzzahl vor, die in dargestellt werden kann (1,9: 9) int
. Es wird keine Garantie gegeben, auch wenn INT_MAX
diese nicht kleiner sein kann!
Der Typ size_t ist der Typ, der vom Operator sizeof zurückgegeben wird. Es ist eine vorzeichenlose Ganzzahl, die die Größe eines auf dem Hostcomputer unterstützten Speicherbereichs in Byte ausdrücken kann. Es ist (normalerweise) mit ptrdiff_t verwandt, dass ptrdiff_t ein vorzeichenbehafteter ganzzahliger Wert ist, so dass sizeof (ptrdiff_t) und sizeof (size_t) gleich sind.
Wenn Sie C-Code schreiben, sollten Sie immer size_t verwenden, wenn Sie sich mit Speicherbereichen befassen.
Der int-Typ hingegen ist im Wesentlichen definiert als die Größe des (vorzeichenbehafteten) Ganzzahlwerts, mit dem der Hostcomputer die Ganzzahlarithmetik am effizientesten ausführen kann. Auf vielen älteren Computern vom Typ PC beträgt der Wert sizeof (size_t) beispielsweise 4 (Byte), sizeof (int) jedoch 2 (Byte). 16-Bit-Arithmetik war schneller als 32-Bit-Arithmetik, obwohl die CPU einen (logischen) Speicherplatz von bis zu 4 GiB verarbeiten konnte.
Verwenden Sie den Typ int nur, wenn Sie Wert auf Effizienz legen, da seine tatsächliche Genauigkeit stark von den Compileroptionen und der Maschinenarchitektur abhängt. Insbesondere spezifiziert der C-Standard die folgenden Invarianten: sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long), wobei der tatsächlichen Darstellung der Genauigkeit, die dem Programmierer für jede von ihnen zur Verfügung steht, keine weiteren Einschränkungen auferlegt werden diese primitiven Typen.
Hinweis: Dies ist NICHT dasselbe wie in Java (das tatsächlich die Bitgenauigkeit für jeden der Typen 'char', 'byte', 'short', 'int' und 'long' angibt).
size_t
Kann die Größe eines einzelnen Objekts darstellen (z. B. Anzahl, Array, Struktur). Der gesamte Speicherbereich kannsize_t
size_t
- ich hoffe, Sie meinen das nicht so. Meistens beschäftigen wir uns nicht mit Arrays, bei denen die Kardinalität von Adressraum + Portabilität überhaupt eine Rolle spielt. In diesen Fällen würden Sie nehmen size_t
. In jedem anderen Fall nehmen Sie Indizes aus (vorzeichenbehafteten) Ganzzahlen. Weil die Verwirrung (die ohne Vorwarnung auftritt), die sich aus dem unerwarteten Unterlaufverhalten von nicht signierten Personen ergibt, häufiger und schlimmer ist als Portabilitätsprobleme, die in den anderen Fällen auftreten können.
Der Typ size_t muss groß genug sein, um die Größe eines möglichen Objekts zu speichern. Int ohne Vorzeichen muss diese Bedingung nicht erfüllen.
In 64-Bit-Systemen können int und unsigned int beispielsweise 32 Bit breit sein, aber size_t muss groß genug sein, um Zahlen größer als 4G zu speichern
size_t
müsste nur so groß sein, wenn der Compiler einen Typ X akzeptieren könnte, so dass sizeof (X) einen Wert größer als 4G ergeben würde. Die meisten Compiler würden z. B. ablehnen typedef unsigned char foo[1000000000000LL][1000000000000LL]
und foo[65536][65536];
könnten sogar zu Recht abgelehnt werden, wenn sie eine dokumentierte implementierungsdefinierte Grenze überschreiten.
Dieser Auszug aus dem glibc-Handbuch 0.02 kann auch für die Erforschung des Themas relevant sein:
Es gibt ein potenzielles Problem mit dem size_t-Typ und den Versionen von GCC vor Release 2.4. ANSI C erfordert, dass size_t immer ein Typ ohne Vorzeichen ist. Aus stddef.h' to be whatever type the system's
Gründen der Kompatibilität mit den Header-Dateien vorhandener Systeme definiert GCC size_t in sys / types.h '. Die meisten Unix-Systeme, die size_t in `sys / types.h 'definieren, definieren es als signierten Typ. Einige Codes in der Bibliothek hängen davon ab, dass size_t ein vorzeichenloser Typ ist, und funktionieren nicht ordnungsgemäß, wenn er signiert ist.
Der GNU C-Bibliothekscode, der erwartet, dass size_t ohne Vorzeichen ist, ist korrekt. Die Definition von size_t als signierter Typ ist falsch. Wir planen, dass GCC in Version 2.4 size_t immer als vorzeichenlosen Typ und fixincludes' script will massage the system's
sys / types.h 'definiert, um keinen Konflikt damit zu verursachen.
In der Zwischenzeit umgehen wir dieses Problem, indem wir GCC explizit anweisen, beim Kompilieren der GNU C-Bibliothek einen vorzeichenlosen Typ für size_t zu verwenden. `configure 'erkennt automatisch, welchen Typ GCC für size_t verwendet, um ihn bei Bedarf zu überschreiben.
Wenn mein Compiler auf 32 Bit eingestellt ist, size_t
ist nichts anderes als ein typedef für unsigned int
. Wenn mein Compiler auf 64 Bit eingestellt ist, size_t
ist nichts anderes als ein typedef für unsigned long long
.
unsigned long
einigen Betriebssystemen wie für beide Fälle definiert werden .
size_t ist die Größe eines Zeigers.
In 32 Bit oder dem gemeinsamen ILP32-Modell (Integer, Long, Pointer) beträgt size_t also 32 Bit. und in 64 Bit oder dem üblichen LP64-Modell (Long, Pointer) beträgt size_t 64 Bit (Ganzzahlen sind immer noch 32 Bit).
Es gibt andere Modelle, aber diese werden von g ++ verwendet (zumindest standardmäßig).
size_t
ist nicht unbedingt so groß wie ein Zeiger, obwohl dies normalerweise der Fall ist. Ein Zeiger muss in der Lage sein, auf eine beliebige Stelle im Speicher zu zeigen. size_t
muss nur groß genug sein, um die Größe des größten Einzelobjekts darzustellen.