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?
Ein aktuelles Beispiel, bei dem sie nicht austauschbar sind, finden Sie in einer Frage, die ich zuvor gestellt habe: stackoverflow.com/questions/645168/…
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.
@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.
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.
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.
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".
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.
Antworten:
Aus der freundlichen Wikipedia :
Überprüfen Sie auch, warum size_t wichtig ist
quelle
/usr/include/stdlib.h
bekommt Linux die Definition von/usr/lib/gcc/x86_64-redhat-linux/5.3.1/include/stddef.h
und darin wird standardmäßig verwendet,long unsigned int
sofern in keiner anderen Header-Datei etwas anderes angegeben ist.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.
quelle
Der
size_t
Typ ist als vorzeichenloser integraler Typ dessizeof
Operators definiert. In der realen Welt wird auf 64-Bit-Plattformen häufig eineint
Definition von 32 Bit (aus Gründen der Abwärtskompatibilität), jedoch einesize_t
Definition von 64 Bit (damit Sie Arrays und Strukturen mit einer Größe von mehr als 4 GiB deklarieren können) angezeigt. Wenn along int
ebenfalls 64-Bit ist, wird dies als LP64-Konvention bezeichnet. Wennlong int
32 Bit, aberlong long int
Zeiger 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. Auchint
ist signiert undsize_t
ist 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
int
ist kleiner alssize_t
und Sie versuchen, die Größe oder den Versatz einer sehr großen Datei oder eines Objekts in einer zu speichern.unsigned int
Es besteht die Möglichkeit, dass diese überläuft und einen Fehler verursacht. Mit aint
besteht auch die Möglichkeit, eine negative Zahl zu erhalten. Wenn einint
oderunsigned int
breiter 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 definiertptrdiff_t
in<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_MAX
und entweder0
oder nach Bedarf zu überprüfen undINT_MIN
die 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.quelle
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.
quelle
size_t
wird 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) istsize_t
".Die Definition von
SIZE_T
finden Sie unter: https://msdn.microsoft.com/en-us/library/cc441980.aspx und https://msdn.microsoft.com/en-us/library/cc230394.aspxFügen Sie hier die erforderlichen Informationen ein:
SIZE_T
ist eineULONG_PTR
Darstellung der maximalen Anzahl von Bytes, auf die ein Zeiger zeigen kann.Dieser Typ wird wie folgt deklariert:
A
ULONG_PTR
ist 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:
quelle
SIZE_T
ist nichtsize_t
, wonach das OP gefragt hat.SIZE_T
ist völlig anders alssize_t
. Sie können keine Variable vom Typ deklarierenSIZE_T
.