Ist size_t die Wortgröße?

Lesezeit: 11 Minuten

Benutzer-Avatar
Weg

Ist size_t die Wortgröße der Maschine, die den Code kompiliert hat?

Parsing mit g++, meine Compiler-Ansichten size_t als ein long unsigned int. Wählt der Compiler intern die Größe von size_toder ist size_t tatsächlich in ein Präprozessor-Makro eingegeben stddef.h auf die Wortgröße, bevor der Compiler aufgerufen wird?

Oder bin ich ganz daneben?

  • Mach dir keine Sorgen. Dies ist eine berechtigte Frage.

    – Scones

    9. Februar 2013 um 22:02 Uhr

  • Was versuchst du zu machen?

    – Nemo

    9. Februar 2013 um 22:05 Uhr

  • Ich versuche nur zu verstehen, was es ist.

    – Weg

    9. Februar 2013 um 22:13 Uhr

  • Dann beantworten die Zitate aus den folgenden Normen Ihre Frage genau. Ihr Compiler kann jeden gewünschten vorzeichenlosen ganzzahligen Typ verwenden size_t solange es groß genug ist, um die Größe eines beliebigen Objekts darzustellen, und das ist alles, was Sie beim Schreiben von C- oder C++-Code davon ausgehen können.

    – Nemo

    9. Februar 2013 um 22:16 Uhr

  • Obwohl alle diese Antworten richtig sind, habe ich niemanden gesehen, der das erwähnt hat size_t ist ziemlich oft die Wortgröße der Maschine. (Und mit “ziemlich oft” meine ich wörtlich: fast alle – wie in, ich habe noch nie von einer einzigen Umgebung gehört, in der dies nicht der Fall ist.)

    – Mystisch

    9. Februar 2013 um 23:42 Uhr


Im C++-Standard [support.types] (18.2) /6: „Der Typus size_t ist ein implementierungsdefinierter unsigned Integer-Typ, der groß genug ist, um die Größe eines beliebigen Objekts in Byte aufzunehmen.”

Dies kann mit einer “Wortgröße” identisch sein oder auch nicht, was auch immer das bedeutet.

  • @ZacharyO’Keefe Ich glaube nicht, dass du das meinst. Ein Byte ist per Definition das kleinste Stück adressierbaren Speichers.

    – Seth Carnegie

    9. Februar 2013 um 22:06 Uhr

  • @ZacharyO’Keefe: Das Zitat aus dem Standard sagt nichts über “am kleinsten” und nichts darüber aus, wie viel Speicher die Maschine zufällig hat. Es ist groß genug, um die Größe zu halten irgendein Objekt die die Implementierung zuordnen kann; das ist der Anfang und das Ende dessen, was man darüber annehmen kann.

    – Nemo

    9. Februar 2013 um 22:13 Uhr


  • size_t muss nicht die Größe eines Zeigers haben, nein. Es ist oft so, aber Sie könnten ein 32-Bit-segmentiertes x86-Modell haben, bei dem ein Zeiger 48 Bit groß ist, aber ein “Objekt” immer noch nur 32 Bit groß sein kann size_t wäre ein 32-Bit-Wert.

    – Mats Petersson

    9. Februar 2013 um 22:19 Uhr

  • @ZacharyO’Keefe – re: “bounded” – faire Frage. Der Compiler weiß nicht, wie viel Speicher das System hat, auf dem das Programm ausgeführt wird, daher hängt die Entscheidung, welches das größtmögliche Objekt ist, nicht von der Menge des verfügbaren Speichers ab. Wenn nicht genügend Speicher vorhanden ist, um ein Objekt zu erstellen, schlägt das Programm zur Laufzeit fehl, manchmal auf mysteriöse Weise.

    – Peter Becker

    9. Februar 2013 um 22:25 Uhr

  • Ich sagte „segmentiertes x86“, was bedeutet, dass jeder Speicherblock einem Segment zugeordnet ist, was bedeutet, dass Zeiger ein 16-Bit-Segment und einen 32-Bit-„Offset innerhalb des Segments“ haben würden. Dies ist ein vollkommen gültiger, wenn auch eher ungewöhnlicher Modus, um den Prozessor zu betreiben.

    – Mats Petersson

    9. Februar 2013 um 22:26 Uhr

Benutzer-Avatar
Jonathan Leffler

Nein; size_t ist nicht unbedingt das, was Sie mit “der Wortgröße” der Maschine meinen, die den Code ausführt (im Fall einer Kreuzkompilierung) oder die den Code kompiliert hat (im Normalfall, wenn der Code auf demselben Maschinentyp ausgeführt wird die den Code kompiliert haben). Es ist ein vorzeichenloser ganzzahliger Typ, der groß genug ist, um die Größe (in Byte) des größten Objekts aufzunehmen, das die Implementierung zuordnen kann.


Etwas Geschichte von sizeof und size_t

Ich weiß nicht wann size_t wurde genau eingeführt, aber es war zwischen 1979 und 1989. Die 1. Ausgabe von K&R Die Programmiersprache C von 1978 hat keine Erwähnung size_t. Die 7. Ausgabe des Unix-Programmierhandbuchs erwähnt dies nicht size_t überhaupt, und das stammt aus dem Jahr 1979. Das Buch “The UNIX Programming Environment” von Kernighan und Pike aus dem Jahr 1984 findet keine Erwähnung size_t im Index (noch von malloc() oder free(), etwas zu meiner Überraschung), aber das ist nur ein Hinweis, nicht schlüssig. Der C89-Standard hat das sicherlich size_t.

Die C99 Begründung dokumentiert einige Informationen über sizeof() und size_t:

6.5.3.4 Die Größe des Operators

Es ist grundlegend für die korrekte Verwendung von Funktionen wie z malloc und fread das
sizeof(char) genau einer sein. In der Praxis bedeutet dies, dass ein Byte in C-Termen die kleinste Speichereinheit ist, selbst wenn diese Einheit 36 ​​Bit breit ist; und alle Objekte bestehen aus einer ganzen Zahl dieser kleinsten Einheiten. Gilt auch, wenn der Speicher bitadressierbar ist. C89 definierte wie K&R das Ergebnis der sizeof Der Operator muss eine Konstante vom Typ einer vorzeichenlosen Ganzzahl sein. Gängige Implementierungen und allgemeine Verwendung haben oft angenommen, dass der resultierende Typ ist int. Alter Code, der von diesem Verhalten abhängt, war nie auf Implementierungen übertragbar, die das Ergebnis als einen anderen Typ als definieren int. Das C89-Komitee hielt es nicht für angemessen, die Sprache zu ändern, um falschen Code zu schützen.

Die Art von sizeofwas auch immer es ist, wird veröffentlicht (in der Kopfzeile der Bibliothek <stddef.h>) wie
size_t, da es für den Programmierer nützlich ist, sich auf diesen Typ beziehen zu können. Diese Anforderung schränkt implizit ein size_t ein Synonym für einen vorhandenen vorzeichenlosen ganzzahligen Typ sein. Beachten Sie auch das, obwohl size_t ist ein vorzeichenloser Typ, sizeof beinhaltet keine arithmetischen Operationen oder Konvertierungen, die zu einem Modulus-Verhalten führen würden, wenn die Größe zu groß ist, um als a dargestellt zu werden
size_twodurch jede Vorstellung zunichte gemacht wird, dass das größte deklarierbare Objekt zu groß sein könnte, um selbst mit an überspannt zu werden unsigned long in C89 bzw uintmax_t im C99. Dies schränkt auch die maximale Anzahl von Elementen ein, die in einem Array deklariert werden können, da für jedes Array a von N
Elemente,

N == sizeof(a)/sizeof(a[0])

Daher size_t ist auch ein praktischer Typ für Array-Größen und wird daher in mehreren Bibliotheksfunktionen verwendet. […]

7.17 Gemeinsame Definitionen

<stddef.h> ist ein Header, der erfunden wurde, um Definitionen verschiedener Typen und Makros bereitzustellen, die häufig in Verbindung mit der Bibliothek verwendet werden: ptrdiff_t, size_t, wchar_tund NULL. Das Einschließen eines beliebigen Headers, der auf eines dieser Makros verweist, definiert es ebenfalls, eine Ausnahme von der üblichen Bibliotheksregel, dass jedes Makro oder jede Funktion zu genau einem Header gehört.

Beachten Sie, dass dies ausdrücklich erwähnt, dass die <stddef.h> wurde vom C89-Komitee erfunden. Ich habe keine Worte gefunden, die das sagen size_t wurde ebenfalls vom C89-Komitee erfunden, aber wenn nicht, war es eine Kodifizierung einer ziemlich neuen Entwicklung in C.


In einem Kommentar zu bmargulies Antwort sagt vonbrand, dass „es [size_t] ist sicherlich ein ANSI-C-ismus’. Ich kann sehr leicht glauben, dass es eine Innovation mit dem ursprünglichen ANSI (ISO) C war, obwohl es etwas seltsam ist, dass die Begründung dies nicht besagt.

  • Wie hängt die Cross-Kompilierung zusammen?

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    9. Februar 2013 um 22:06 Uhr

  • Die Frage fragt, ob die Größe von size_t hängt von der Wortgröße der Maschine ab, auf der der Code kompiliert wurde. Wenn Sie für einen 8-Bit- oder 16-Bit-Mikroprozessor auf einem 64-Bit-Computer crosskompilieren, stehen die Chancen gut, dass die Größe von size_t denn das Programm hat keine Ähnlichkeit mit der Größe des Wortes auf der Maschine, die das Kompilieren durchführt – daher meine Erwähnung des Cross-Kompilierens.

    – Jonathan Leffler

    9. Februar 2013 um 22:10 Uhr

  • @JonathanLeffler ‘Es ist ein vorzeichenloser Integer-Typ, der groß genug ist, um die Größe (in Bytes) des größten Objekts aufzunehmen, das die Implementierung zuweisen kann’. Da Sie nur den Adressraum zuweisen können, size_t muss dadurch begrenzt werden, wie viel Speicher sich im Adressraum befindet?

    – Weg

    9. Februar 2013 um 22:29 Uhr

  • @ZacharyO’Keefe: Normalerweise haben Sie Recht, aber behaupten muss ist gefährlich, es sei denn, Sie müssen die Frage überhaupt nicht stellen (und es kann gefährlich sein, sie zu behaupten, selbst wenn Sie glauben, die Antwort in- und auswendig zu kennen). Der C89-Standard sagt das einfach <stddef.h> Header definiert einen Typ ‘size_t Dies ist der vorzeichenlose ganzzahlige Typ des Ergebnisses von sizeof Operator‘. C99 ändert „Integer“ in „Ganzzahl“ und C11 ist dasselbe wie C99.

    – Jonathan Leffler

    9. Februar 2013 um 22:59 Uhr

  • Der Standard ist nicht viel informativer über die sizeof Operator; es sagt: ‘Der Wert des Ergebnisses [of sizeof] ist implementierungsdefiniert, und sein Typ (ein vorzeichenloser ganzzahliger Typ) ist size_tdefiniert in <stddef.h> (und andere Überschriften).

    – Jonathan Leffler

    9. Februar 2013 um 23:00 Uhr

Nicht unbedingt. Die C-ISO-Spezifikation (§17.1/2) definiert size_t wie

size_t, das ist der vorzeichenlose ganzzahlige Typ des Ergebnisses von sizeof Operator

Mit anderen Worten, size_t muss groß genug sein, um die Größe jedes Ausdrucks aufzunehmen, der erzeugt werden könnte sizeof. Dies könnte die Maschinenwortgröße sein, aber sie könnte dramatisch kleiner sein (wenn der Compiler beispielsweise die maximale Größe von Arrays oder Objekten begrenzt hat) oder dramatisch größer (wenn der Compiler Sie Objekte erstellen lassen würde, die so groß sind, dass eine einzelne Maschine Word konnte die Größe dieses Objekts nicht speichern).

Hoffe das hilft!

  • Ahh. So size_t wird durch die Implementierung festgelegt, was mein Compiler zulässt? Da die maximale Speichermenge, die ich zuweisen kann, klar durch die Menge an physischem Speicher begrenzt ist, die ich habe, ist size_t begrenzt durch, wie viel physischen Speicher ich zum Adressraum beitragen muss?

    – Weg

    9. Februar 2013 um 22:27 Uhr

  • @ZacharyO’Keefe- Es liegt ganz im Ermessen des Compilers. Das könnte der Compiler sehr vernünftig machen size_t groß genug, um die Differenz zweier beliebiger physikalischer Adressen aufzunehmen (die Differenz der End- und Startadressen eines Objekts gibt seine Größe an). Auf der anderen Seite könnten Sie sich ein seltsames Setup vorstellen, bei dem Sie einen 128-Bit-Adressraum haben, aber einen Zuordner, der nicht mehr als 4 GB zuweisen kann. In diesem Fall könnte der Computer eine 32-Bit-Ganzzahl verwenden size_t. Die einzige Möglichkeit, dies herauszufinden, besteht darin, in die Compiler-Dokumentation zu schauen.

    – Vorlagentypdef

    9. Februar 2013 um 22:31 Uhr

  • Danke, das hat auf jeden Fall geholfen. Was passiert also, wenn ich versuche, ein Array von 2^size_t Zeichen (statisch oder dynamisch) zuzuweisen? (dh 1 mehr als size_t darstellen kann). Wird sich der Compiler beschweren?

    – Weg

    9. Februar 2013 um 22:47 Uhr

  • @ZacharyO’Keefe: Statisch wird sich der Compiler wahrscheinlich beschweren. Dynamisch wird es wahrscheinlich umlaufen und Sie werden am Ende 0 zuweisen.

    – icktoofay

    9. Februar 2013 um 22:49 Uhr

  • @ZacharyO’Keefe- Das Argument dafür malloc (C) und operator new (C++) hat einen Typ size_twenn Sie also versuchen, einen größeren Wert zu übergeben, wird die Zahl überlaufen.

    – Vorlagentypdef

    9. Februar 2013 um 22:50 Uhr

Benutzer-Avatar
bmargulies

size_t war ursprünglich nur eine Typedef in sys/types.h (traditionell unter Unix/Linux). Es wurde angenommen, dass es “groß genug” für beispielsweise die maximale Größe einer Datei oder die maximale Zuweisung mit malloc ist. Im Laufe der Zeit haben sich jedoch Standardkomitees daran gehalten, und so wurde es in viele verschiedene Header-Dateien kopiert und jedes Mal mit seinem eigenen #ifdef-Schutz vor Mehrfachdefinition geschützt. Andererseits trübte das Aufkommen von 64-Bit-Systemen mit sehr großen potenziellen Dateigrößen seine Rolle. Es ist also ein bisschen wie ein Palimpset.

Sprachstandards bezeichnen es jetzt als in stddef.h lebend. Es hat keine notwendige Beziehung zur Hardware-Wortgröße und keine Compiler-Magie. Siehe andere Antworten in Bezug darauf, was diese Standards darüber aussagen, wie groß es ist.

Solche Definitionen sind alle implementierungsdefiniert. Ich würde sizeof(char *) oder vielleicht sizeof(void *) verwenden, wenn ich eine bestmögliche Größe benötigen würde. Das Beste, was dies ergibt, ist die scheinbare Wortgröße, die die Software verwendet … was die Hardware wirklich hat, kann anders sein (z. B. kann ein 32-Bit-System 64-Bit-Integer per Software unterstützen).

Auch wenn Sie neu in den C-Sprachen sind, finden Sie in stdint.h alle möglichen Materialien zu ganzzahligen Größen.

Benutzer-Avatar
Damon

Obwohl die Definition nicht direkt angibt, welcher Typ genau ist size_t ist, und erfordert nicht einmal eine Mindestgröße, gibt es indirekt einige gute Hinweise. EIN size_t muss in der Lage sein, die Größe in Bytes eines beliebigen Objekts zu enthalten, mit anderen Worten, es muss die Größe des größtmöglichen Objekts enthalten können.

Das größtmögliche Objekt ist ein Array (oder eine Struktur) mit einer Größe, die dem gesamten verfügbaren Adressraum entspricht. Ein Verweis auf a ist nicht möglich größer Objekt auf sinnvolle Weise, und abgesehen von der Verfügbarkeit von Auslagerungsspeicher gibt es keinen Grund, warum dies erforderlich sein sollte kleiner.

Daher ist nach dem Wortlaut der Definition size_t muss mindestens 32 Bit auf einer 32-Bit-Architektur und mindestens 64 Bit auf einem 64-Bit-System sein. Es ist natürlich möglich, eine Implementierung größer zu wählen size_taber das ist normalerweise nicht der Fall.

1382500cookie-checkIst size_t die Wortgröße?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy