In mehreren C ++ - Beispielen sehe ich eine Verwendung des Typs, size_t
bei dem ich eine einfache verwendet hätte int
. Was ist der Unterschied und warum size_t
sollte es besser sein?
In mehreren C ++ - Beispielen sehe ich eine Verwendung des Typs, size_t
bei dem ich eine einfache verwendet hätte int
. Was ist der Unterschied und warum size_t
sollte es besser sein?
Antworten:
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
/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.
Der size_t
Typ ist als vorzeichenloser integraler Typ des sizeof
Operators definiert. In der realen Welt wird auf 64-Bit-Plattformen häufig eine int
Definition von 32 Bit (aus Gründen der Abwärtskompatibilität), jedoch eine size_t
Definition von 64 Bit (damit Sie Arrays und Strukturen mit einer Größe von mehr als 4 GiB deklarieren können) angezeigt. Wenn a long int
ebenfalls 64-Bit ist, wird dies als LP64-Konvention bezeichnet. Wenn long int
32 Bit, aber long 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. Auch int
ist signiert und size_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 als size_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 a int
besteht auch die Möglichkeit, eine negative Zahl zu erhalten. Wenn ein int
oder unsigned 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 definiert ptrdiff_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 entweder 0
oder nach Bedarf zu überprüfen und INT_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.
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.
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) ist size_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.aspx
Fügen Sie hier die erforderlichen Informationen ein:
SIZE_T
ist eine ULONG_PTR
Darstellung der maximalen Anzahl von Bytes, auf die ein Zeiger zeigen kann.
Dieser Typ wird wie folgt deklariert:
typedef ULONG_PTR SIZE_T;
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:
typedef unsigned __int3264 ULONG_PTR;
SIZE_T
ist nicht size_t
, wonach das OP gefragt hat.
SIZE_T
ist völlig anders als size_t
. Sie können keine Variable vom Typ deklarieren SIZE_T
.