814 Stimmen

Was ist size_t in C?

Ich bin verwirrt mit size_t in C. Ich weiß, dass es von der sizeof Betreiber. Aber was genau ist er? Ist es ein Datentyp?

Nehmen wir an, ich habe eine for Schleife:

for(i = 0; i < some_size; i++)

Soll ich die int i; o size_t i; ?

570voto

sblom Punkte 26177

Aus Wikipedia :

Gemäß der ISO C-Norm von 1999 (C99), size_t ist eine Ganzzahl ohne Vorzeichen Typ mit mindestens 16 Bit (siehe Abschnitte 7.17 und 7.18.3).

size_t ist ein Datentyp ohne Vorzeichen der in mehreren C/C++-Standards definiert ist, z.B. der C99 ISO/IEC 9899 Standard, der definiert ist in stddef.h . 1 Sie kann weiter importiert werden durch Einbeziehung von stdlib.h da diese Datei intern unter enthält stddef.h .

Dieser Typ wird verwendet, um die Größe eines Objekts. Bibliotheksfunktionen die Größen annehmen oder zurückgeben, erwarten, dass sie vom Typ sein oder den Rückgabetyp von size_t . Außerdem ist die am häufigsten am häufigsten verwendete compilerbasierte Operator sizeof auf einen konstanten Wert konstanten Wert auswerten, der kompatibel ist mit size_t .

Dies ist eine Konsequenz, size_t ist ein Typ, der garantiert jeden Array-Index aufnehmen kann.

285voto

Alok Singhal Punkte 87419

size_t ist ein Typ ohne Vorzeichen. Er kann also keine negativen Werte (<0) darstellen. Sie verwenden ihn, wenn Sie etwas zählen und sicher sind, dass es nicht negativ sein kann. Zum Beispiel, strlen() gibt eine size_t weil die Länge einer Zeichenkette mindestens 0 sein muss.

Wenn in Ihrem Beispiel der Schleifenindex immer größer als 0 sein wird, könnte es sinnvoll sein, die size_t oder jeden anderen vorzeichenlosen Datentyp.

Wenn Sie eine size_t Objekts müssen Sie sicherstellen, dass Sie in allen Kontexten, in denen es verwendet wird, einschließlich der Arithmetik, nicht-negative Werte wünschen. Nehmen wir zum Beispiel an, Sie haben:

size_t s1 = strlen(str1);
size_t s2 = strlen(str2);

und Sie wollen die Differenz der Längen von str2 y str1 . Das können Sie nicht tun:

int diff = s2 - s1; /* bad */

Dies liegt daran, dass der Wert, der dem diff wird immer eine positive Zahl sein, auch wenn s2 < s1 weil die Berechnung mit vorzeichenlosen Typen durchgeführt wird. In diesem Fall, je nach Anwendungsfall, ist es besser, wenn Sie int (oder long long ) para s1 y s2 .

Es gibt einige Funktionen in C/POSIX, die Folgendes verwenden könnten/sollten size_t , aber aus historischen Gründen nicht tun. Zum Beispiel ist der zweite Parameter von fgets sollte idealerweise sein size_t sondern ist int .

108voto

Arjun Sreedharan Punkte 10254

size_t ist ein Typ, der jeden Array-Index enthalten kann.

Je nach Implementierung kann es sich um eine der folgenden handeln:

unsigned char

unsigned short

unsigned int

unsigned long

unsigned long long

So geht's size_t ist definiert in stddef.h meiner Maschine:

typedef unsigned long size_t;

96voto

Wenn Sie ein empirischer Typ sind ,

echo | gcc -E -xc -include 'stddef.h' - | grep size_t

Ausgabe für Ubuntu 14.04 64-bit GCC 4.8:

typedef long unsigned int size_t;

Beachten Sie, dass stddef.h wird von GCC und nicht von glibc unter src/gcc/ginclude/stddef.h im GCC 4.2.

Interessante C99-Auftritte

  • malloc nimmt size_t als Argument und bestimmt damit die maximale Größe, die zugewiesen werden kann.

    Und da sie auch von sizeof Ich denke, dass es die maximale Größe eines Arrays begrenzt.

    Siehe auch: Was ist die maximale Größe eines Arrays in C?

29voto

Davislor Punkte 13072

Zu den Gründen size_t zu existieren, und wie wir hierher gekommen sind:

Ganz pragmatisch ausgedrückt, size_t y ptrdiff_t sind bei einer 64-Bit-Implementierung garantiert 64 Bit breit, bei einer 32-Bit-Implementierung 32 Bit und so weiter. Sie könnten keinen existierenden Typ dazu zwingen, dies bei jedem Compiler zu bedeuten, ohne Legacy-Code zu zerstören.

A size_t o ptrdiff_t ist nicht unbedingt dasselbe wie ein intptr_t o uintptr_t . Sie waren auf bestimmten Architekturen, die noch in Gebrauch waren, als size_t y ptrdiff_t wurden in den späten 1980er Jahren in die Norm aufgenommen und wurden obsolet, als C99 fügte viele neue Arten, aber noch nicht gegangen (wie 16-Bit-Windows). Der x86 im geschützten 16-Bit-Modus hatte einen segmentierten Speicher, bei dem das größtmögliche Array oder die größte Struktur nur 65.536 Byte groß sein konnte, aber ein far Der Zeiger musste 32 Bit breit sein, breiter als die Register. Auf diese, intptr_t wäre 32 Bit breit gewesen, aber size_t y ptrdiff_t könnte 16 Bit breit sein und in ein Register passen. Und wer wusste schon, was für ein Betriebssystem in der Zukunft geschrieben werden würde? Theoretisch bietet die i386-Architektur ein 32-Bit-Segmentierungsmodell mit 48-Bit-Zeigern, das jedoch von keinem Betriebssystem jemals tatsächlich verwendet wurde.

Der Typ eines Speicher-Offsets konnte nicht long denn viel zu viel veralteter Code geht davon aus, dass long ist genau 32 Bit breit. Diese Annahme wurde sogar in die UNIX- und Windows-APIs eingebaut. Leider ging auch eine Menge anderer Legacy-Code davon aus, dass ein long ist breit genug, um einen Zeiger, einen Dateiversatz, die Anzahl der seit 1970 verstrichenen Sekunden usw. aufzunehmen. POSIX bietet nun eine standardisierte Möglichkeit, die letztere Annahme anstelle der ersten zu erzwingen, aber keine der beiden Annahmen ist portabel zu machen.

Das kann nicht sein int weil nur eine kleine Handvoll Compiler in den 90er Jahren die int 64 Bit breit. Dann wurden sie wirklich seltsam und behielten long 32 Bit breit. Die nächste Revision der Norm erklärte es für illegal, wenn int breiter sein als long pero int ist auf den meisten 64-Bit-Systemen immer noch 32 Bit breit.

Das kann nicht sein long long int die ohnehin erst später hinzugefügt wurde, da sie so angelegt wurde, dass sie auch auf 32-Bit-Systemen mindestens 64 Bit breit ist.

Es wurde also ein neuer Typ benötigt. Selbst wenn dies nicht der Fall wäre, bedeuteten all diese anderen Typen etwas anderes als einen Offset innerhalb eines Arrays oder Objekts. Und wenn es eine Lehre aus dem Fiasko der 32-zu-64-Bit-Migration gab, dann die, dass man sich genau überlegen sollte, welche Eigenschaften ein Typ haben muss, und nicht einen Typ verwenden sollte, der in verschiedenen Programmen etwas anderes bedeutet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X