Was ist der Unterschied zwischen size_t und int in C ++?


173

In mehreren C ++ - Beispielen sehe ich eine Verwendung des Typs, size_tbei dem ich eine einfache verwendet hätte int. Was ist der Unterschied und warum size_tsollte es besser sein?


3
Ein aktuelles Beispiel, bei dem sie nicht austauschbar sind, finden Sie in einer Frage, die ich zuvor gestellt habe: stackoverflow.com/questions/645168/…
Tyler McHenry

Antworten:


152

Aus der freundlichen Wikipedia :

Die Header-Dateien stdlib.h und stddef.h definieren einen Datentyp namens size_t, der zur Darstellung der Größe eines Objekts verwendet wird. Bibliotheksfunktionen, die Größen annehmen, erwarten, dass sie vom Typ size_t sind, und der Operator sizeof ergibt size_t.

Der tatsächliche Typ von size_t ist plattformabhängig. Ein häufiger Fehler besteht darin, anzunehmen, dass size_t mit int ohne Vorzeichen identisch ist, was zu Programmierfehlern führen kann, insbesondere wenn 64-Bit-Architekturen häufiger eingesetzt werden.

Überprüfen Sie auch, warum size_t wichtig ist


76
Und was ist size_t?
NDEthos

8
@NDEthos Es kommt darauf an! Hier /usr/include/stdlib.hbekommt Linux die Definition von /usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.hund darin wird standardmäßig verwendet, long unsigned intsofern in keiner anderen Header-Datei etwas anderes angegeben ist.
David Tonhofer

1
Ich bestätige, dass size_t to int tuncation gefährlich ist . Dies mag nicht zum Thema gehören, aber wie kann man einen Patch alleine schreiben, um diese Art von Fehlern zu beheben, wenn sie tausende Male im Linux-Kernel auftreten?
user2284570

36

size_t ist der Typ, der zur Darstellung von Größen verwendet wird (wie der Name schon sagt). Die Plattform (und möglicherweise auch die Implementierung) ist abhängig und sollte nur für diesen Zweck verwendet werden. Offensichtlich ist size_t für eine Größe ohne Vorzeichen. Viele stdlib-Funktionen, einschließlich malloc, sizeof und verschiedener Zeichenfolgenoperationsfunktionen, verwenden size_t als Datentyp.

Ein int ist standardmäßig signiert, und obwohl seine Größe auch plattformabhängig ist, beträgt es auf den meisten modernen Computern feste 32 Bit (und obwohl size_t bei einer 64-Bit-Architektur 64 Bit beträgt, bleibt int auf diesen Architekturen 32 Bit lang).

Zusammenfassend: Verwenden Sie size_t, um die Größe eines Objekts darzustellen, und int (oder long) in anderen Fällen.


12

Der size_tTyp ist als vorzeichenloser integraler Typ des sizeofOperators definiert. In der realen Welt wird auf 64-Bit-Plattformen häufig eine intDefinition von 32 Bit (aus Gründen der Abwärtskompatibilität), jedoch eine size_tDefinition von 64 Bit (damit Sie Arrays und Strukturen mit einer Größe von mehr als 4 GiB deklarieren können) angezeigt. Wenn a long intebenfalls 64-Bit ist, wird dies als LP64-Konvention bezeichnet. Wenn long int32 Bit, aber long long intZeiger 64 Bit sind, ist das LLP64. Möglicherweise erhalten Sie auch das Gegenteil, ein Programm, das 64-Bit-Anweisungen für die Geschwindigkeit verwendet, aber 32-Bit-Zeiger, um Speicherplatz zu sparen. Auch intist signiert und size_tist nicht signiert.

In der Vergangenheit gab es eine Reihe anderer Plattformen, auf denen Adressen breiter oder kürzer als die native Größe von waren int . Tatsächlich war dies in den 70er und frühen 80er Jahren mehr als üblich: Alle gängigen 8-Bit-Mikrocomputer hatten 8-Bit-Register und 16-Bit-Adressen, und der Übergang zwischen 16 und 32 Bit erzeugte auch viele Maschinen, die hatte Adressen, die breiter waren als ihre Register. Gelegentlich sehe ich hier immer noch Fragen zu Borland Turbo C für MS-DOS, dessen großer Speichermodus 20-Bit-Adressen in 32-Bit auf einer 16-Bit-CPU gespeichert hatte (die jedoch den 32-Bit-Befehlssatz des 80386 unterstützen könnten). Das Motorola 68000 hatte eine 16-Bit-ALU mit 32-Bit-Registern und -Adressen. Es gab IBM-Mainframes mit 15-Bit-, 24-Bit- oder 31-Bit-Adressen. In eingebetteten Systemen werden auch weiterhin unterschiedliche ALU- und Adressbusgrößen angezeigt.

Jede Zeit intist kleiner als size_tund Sie versuchen, die Größe oder den Versatz einer sehr großen Datei oder eines Objekts in einer zu speichern. unsigned intEs besteht die Möglichkeit, dass diese überläuft und einen Fehler verursacht. Mit a intbesteht auch die Möglichkeit, eine negative Zahl zu erhalten. Wenn ein intoder unsigned intbreiter ist, wird das Programm korrekt ausgeführt, es wird jedoch Speicherplatz verschwendet.

Sie sollten im Allgemeinen den richtigen Typ für diesen Zweck verwenden, wenn Sie Portabilität wünschen. Viele Leute werden empfehlen, dass Sie signierte Mathematik anstelle von nicht signierten verwenden (um böse, subtile Fehler wie zu vermeiden 1U < -3). Zu diesem Zweck sind die Standardbibliothek definiert ptrdiff_tin <stddef.h>als signierte Typ des Ergebnisses eines Zeigers von dem anderen subtrahiert wird .

Eine Problemumgehung könnte jedoch darin bestehen, alle Adressen und Offsets gegen INT_MAXund entweder 0oder nach Bedarf zu überprüfen und INT_MINdie Compiler-Warnungen zum Vergleichen von signierten und nicht signierten Mengen zu aktivieren, falls Sie eine verpassen. Sie sollten Ihre Array-Zugriffe in C ohnehin immer und immer auf Überlauf überprüfen.


8

Dies liegt daran, dass size_t alles andere als ein int (möglicherweise eine struct) sein kann. Die Idee ist, dass es seinen Job vom zugrunde liegenden Typ entkoppelt.


8
Ich denke, dass size_t tatsächlich ein Alias ​​für eine vorzeichenlose Ganzzahl ist, also kann es keine Struktur sein. Ich habe jedoch momentan keine Referenz zur Hand, um dies zu sichern.
Entspannen Sie sich

9
@unwind: C99: TC3, 7.17 §2
Christoph

1
@danio Warum ist es so? Kannst du das erklären?
Rüppells Geier

2
Ich würde nicht auf cplusplus verlinken, wenn ich du wäre! Wenn Sie Kapitel, Verse, Absätze und Zeilen nicht zitieren können, dann ist alles nur Hörensagen! :-)
graham.reeds

1
size_twird als vorzeichenloser Integer- Typ angegeben. C11 §6.5.3.4 5 "Der Wert des Ergebnisses beider Operatoren ( sizeof _Alignof) ist implementierungsdefiniert und sein Typ (ein vorzeichenloser Integer-Typ) ist size_t".
chux - Wiedereinsetzung Monica

-1

Die Definition von SIZE_Tfinden Sie unter: https://msdn.microsoft.com/en-us/library/cc441980.aspx und https://msdn.microsoft.com/en-us/library/cc230394.aspx

Fügen Sie hier die erforderlichen Informationen ein:

SIZE_Tist eine ULONG_PTRDarstellung der maximalen Anzahl von Bytes, auf die ein Zeiger zeigen kann.

Dieser Typ wird wie folgt deklariert:

typedef ULONG_PTR SIZE_T;

A ULONG_PTRist ein vorzeichenloser langer Typ, der für die Zeigergenauigkeit verwendet wird. Es wird verwendet, wenn ein Zeiger auf einen langen Typ umgewandelt wird, um eine Zeigerarithmetik durchzuführen.

Dieser Typ wird wie folgt deklariert:

typedef unsigned __int3264 ULONG_PTR;

2
SIZE_Tist nicht size_t, wonach das OP gefragt hat.
Ikegami

2
Dies ist eine Microsoft-Erweiterung, die nicht Teil der Standardsprache ist.
Davislor

SIZE_Tist völlig anders als size_t. Sie können keine Variable vom Typ deklarieren SIZE_T.
Calocedrus
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.