C: Warum ist size_t kein C-Schlüsselwort?

Lesezeit: 9 Minuten

Benutzer-Avatar
Ashwin Nanjappa

sizeof ist ein C Stichwort. Es gibt die Größe in einem Typ namens zurück size_t. Jedoch, size_t ist nicht ein Schlüsselwort, sondern wird hauptsächlich in definiert stddef.h und wahrscheinlich auch andere C-Standard-Header-Dateien.

Stellen Sie sich ein Szenario vor, in dem Sie ein C-Programm erstellen möchten, das nicht enthalten alle C-Standard-Header oder -Bibliotheken. (Wie zum Beispiel, wenn Sie einen OS-Kernel erstellen.) Nun, in einem solchen Code, sizeof kann verwendet werden (es ist ein C-Schlüsselwort, also ist es ein Teil der Sprache), aber der zurückgegebene Typ (size_t) ist nicht verfügbar!

Bedeutet dies nicht irgendein Problem in der C-Standardspezifikation? Können Sie das klären?

  • Viele Header sind absolut sicher und sinnvoll einzufügen, sogar in einen Betriebssystemkern. Das Problem, über das Sie sich in einem Kernel Sorgen machen, ist das Verlinken mit Bibliotheken, ohne Header.

    – RBerteig

    11. April 2009 um 8:08 Uhr

  • RBerteig: Nur um der Argumentation willen sagen wir, ich möchte ein C-Programm erstellen, das nur die Sprache verwendet, keine Header/Bibliotheken, und ich möchte sizeof verwenden.

    – Ashwin Nanjappa

    11. April 2009 um 8:10 Uhr

  • Sie müssten höchstwahrscheinlich Ihre eigene Implementierungsbibliothek in Assembly schreiben. Ohne die Header und Bibliotheken (und die damit verbundenen Funktionen) können Sie nicht viel tun.

    – Chris Lutz

    11. April 2009 um 8:11 Uhr

  • Standardkopfzeilen sind Teil der Sprache. Viele definieren die Schnittstellen zu den Standardbibliotheken, und es gibt gute Gründe, diese nicht in einem Kernel oder einem tief eingebetteten System zu verwenden. Aber andere definieren in erster Linie nützliche Dinge in Bezug auf die Implementierung: stddef.h, limits.h sind Beispiele.

    – RBerteig

    11. April 2009 um 8:16 Uhr

  • Chris und RBerteig: Ja, aber betrachten wir ein Programm, das keine Header/Bibliotheken verwendet, sondern nur ein paar arithmetische Aussagen macht.

    – Ashwin Nanjappa

    11. April 2009 um 8:59 Uhr

Benutzer-Avatar
Simon Breitkopf

Sie gibt nicht buchstäblich einen Wert vom Typ size_t zurück, da size_t kein konkreter Typ an sich ist, sondern eher eine Typdefinition für einen nicht spezifizierten eingebauten Typ. Typedef-Bezeichner (z. B. size_t) sind vollständig äquivalent zu ihren jeweiligen zugrunde liegenden Typen (und werden zur Kompilierzeit in diese konvertiert). Wenn size_t auf Ihrer Plattform als unsigned int definiert ist, gibt sizeof einen unsigned int zurück, wenn es auf Ihrem System kompiliert wird. size_t ist nur eine praktische Möglichkeit, die Portabilität aufrechtzuerhalten, und muss nur in stddef.h aufgenommen werden, wenn Sie es explizit nach Namen verwenden.

  • +1, die richtige Antwort. Alles, was eine Typedef zurückgibt, kann nicht wirklich als Rückgabe dieser Typedef bezeichnet werden. Es gibt zurück, worauf die Typedef hinausläuft. Wenn Sie Portabilität wünschen, schließen Sie stddef.h ein. Wenn Sie dies nicht tun, schlagen Sie die Definition von size_t auf Ihrer Plattform nach und verwenden Sie stattdessen direkt diesen Typ.

    – Daniel Earwicker

    11. April 2009 um 8:33 Uhr

  • Volte: Ich sehe das Bild jetzt. Daher kann der Compiler size_t nicht “sehen”, sondern einen Typ für sizeof verwenden, der genau dem entspricht, für den size_t in den Headern, die mit dem Compiler geliefert werden, typedef ist.

    – Ashwin Nanjappa

    11. April 2009 um 9:08 Uhr

  • Wie in meiner Antwort ausgeführt, hat der Compiler die Typedef von size)t “gesehen”, als er selbst kompiliert wurde – in gewissem Sinne “weiß” er über size_t

    anon

    11. April 2009 um 9:10 Uhr

  • Neil Butterworth: Ich konnte es in Ihrer Antwort nicht verstehen, aber ich verstand es, als ich Voltes Antwort las 🙂 Nun, um die Sache ein wenig zu komplizieren, was wird mit einem Cross-Compiler passieren, dessen native und Zielplattform unterschiedliche size_t erfordern? 😉

    – Ashwin Nanjappa

    11. April 2009 um 9:19 Uhr

  • Das size_t, das der Compiler sah, ist bestenfalls ein Implementierungsdetail, da konforme C-Compiler in jeder Sprache geschrieben werden könnten. Es ist Standard, dass der Rückgabetyp von sizeof äquivalent zu size_t ist, aber der tatsächliche zugrunde liegende Typ wird der Implementierung des Compilers überlassen.

    – Simon Breitkopf

    11. April 2009 um 9:34 Uhr

sizeof ist ein Schlüsselwort, weil es trotz seines Namens und seiner Verwendung ein Schlüsselwort ist Operator wie + oder = oder < eher als ein Funktion wie printf() oder atoi() oder fgets(). Viele Leute vergessen das (oder wissen es einfach nicht). sizeof ist eigentlich ein Operator, und ist stets zur Kompilierzeit und nicht zur Laufzeit aufgelöst.

Die C-Sprache braucht nicht size_t eine brauchbare, konsistente Sprache zu sein. Das ist nur ein Teil der Standardbibliothek. Die C-Sprache benötigt alle Operatoren. Wenn, statt +C hat das Schlüsselwort verwendet plus Um Zahlen zu addieren, würden Sie daraus einen Operator machen.

Außerdem mache ich eine semi-implizite Umformung von size_ts zu unsigned ints (und regelmäßig ints, aber Kernighan und Ritchie werden mich eines Tages dafür schlagen) die ganze Zeit. Sie können den Rückgabetyp a zuweisen sizeof an ein int, wenn Sie möchten, aber bei meiner Arbeit gebe ich es normalerweise einfach direkt an a weiter malloc() oder so.

  • Chris: Danke für diese überzeugende Erklärung. Aber impliziert das nicht, dass size_t eng in C ist, wie int/char. Warum es dann in einem Header definieren?

    – Ashwin Nanjappa

    11. April 2009 um 9:04 Uhr

  • Nicht, dass es weit verbreitet ist (oder sogar unterstützt wird), aber für Arrays mit variabler Länge im C99-Stil wird sizeof zur Laufzeit ausgewertet.

    – Michael Burr

    11. April 2009 um 9:49 Uhr

  • @Michael – Ernsthaft? Verdammt. Allerdings wird C99 wirklich schlecht unterstützt, also bleibe ich für eine Weile bei meinem malloc() und realloc() und free(), um diese Arbeit zu erledigen.

    – Chris Lutz

    11. April 2009 um 9:54 Uhr

  • Michael Burr: Das ist mir neu! Danke für den Hinweis 🙂

    – Ashwin Nanjappa

    11. April 2009 um 9:59 Uhr

  • @ChrisLutz Seit wann wird C99 schlecht unterstützt? Das ist mir neu. Es liegt nicht daran, dass MSVC es versäumt, einen Standard zu implementieren, der mehr als ein Jahrzehnt alt ist, dass dieser Standard schlecht unterstützt wird …

    – rubenvb

    27. Mai 2013 um 14:45 Uhr

Benutzer-Avatar
DevSolar

Einige Header aus dem C-Standard sind für a definiert freistehend Umgebung, dh geeignet für den Einsatz zB in einem Betriebssystem-Kernel. Sie definieren keine Funktionen, sondern definieren und typedefs.

Sie sind float.h, iso646.h, limits.h, stdarg.h, stdbool.h, stddef.h und stdint.h.

Wenn Sie an einem Betriebssystem arbeiten, ist es keine schlechte Idee, damit zu beginnen diese Kopfzeilen. Ihre Verfügbarkeit macht viele Dinge in Ihrem Kernel einfacher. Besonders stdint.h wird praktisch (uint32_t et al.).

  • DevSolar: Der OS-Kernel war nur ein Beispiel, betrachten Sie stattdessen einen Fall, in dem ich ein C-Programm schreiben möchte, das sizeof verwendet, aber keinen C-Header enthält. Danke für die Info zu den Headern der freistehenden Umgebung, das war mir nicht bewusst.

    – Ashwin Nanjappa

    11. April 2009 um 9:16 Uhr

Bedeutet dies nicht irgendein Problem in der C-Standardspezifikation?

Schlagen Sie den Unterschied zwischen einer gehosteten C-Implementierung und einer freistehenden C-Implementierung nach. Die freistehende (C99) Implementierung ist erforderlich, um Header bereitzustellen:

  • <float.h>
  • <iso646.h>
  • <limits.h>
  • <stdarg.h>
  • <stdbool.h>
  • <stddef.h>
  • <stdint.h>

Diese Header definieren überhaupt keine Funktionen. Sie definieren Teile der Sprache, die etwas Compiler-spezifisch sind (z. B. die offsetof Makro ein <stddef.h>und das Variablenargument listet Makros und Typen auf <stdarg.h>), aber sie können gehandhabt werden, ohne tatsächlich als vollständige Schlüsselwörter in die Sprache eingebaut zu werden.

Das bedeutet, dass Sie selbst in Ihrem hypothetischen Kernel erwarten sollten, dass der C-Compiler diese Header und alle zugrunde liegenden Unterstützungsfunktionen bereitstellt – obwohl Sie alles andere bereitstellen.

Benutzer-Avatar
Michael Burr

Ich denke, dass die Hauptgründe dafür size_t ist kein Schlüsselwort sind:

  • es gibt keinen zwingenden Grund dafür. Die Designer der Sprachen C und C++ haben es immer bevorzugt, Sprachfeatures in der Bibliothek zu implementieren, wenn dies möglich und sinnvoll ist
  • Das Hinzufügen von Schlüsselwörtern zu einer Sprache kann Probleme für einen vorhandenen Legacy-Code verursachen. Dies ist ein weiterer Grund, warum sie im Allgemeinen dem Hinzufügen neuer Schlüsselwörter widerstehen.

Wenn Sie beispielsweise die nächste große Überarbeitung des C++-Standards diskutieren, Stroustrup hatte dies zu sagen:

Die C++0x-Verbesserungen sollten so durchgeführt werden, dass die resultierende Sprache einfacher zu erlernen und zu verwenden ist. Zu den Faustregeln für das Komitee gehören:

...

  • Bevorzugen Sie Standardbibliothekseinrichtungen gegenüber Spracherweiterungen

...

  • Trotzdem fühlt es sich ziemlich seltsam an, dass ein eingebauter Operator sizeof ergibt einen Ausdruck eines Bibliothekstyps size_t. 🙂

    – musiphil

    10. April 2014 um 20:57 Uhr

  • @musiphil: Es könnte sich weniger seltsam anfühlen, es so zu sehen: Die Bibliothek muss definieren size_t der Typ zu sein, dass die sizeof Betreiber ergibt.

    – Michael Burr

    10. April 2014 um 21:24 Uhr

Es gibt keinen Grund, stddef.h nicht einzubinden, selbst wenn Sie an einem Kernel arbeiten – es definiert Typgrößen für Ihren spezifischen Compiler, die jeder Code benötigt.

Beachten Sie auch, dass fast alle C-Compiler selbst kompiliert sind. Der eigentliche Compilercode für den sizeof-Operator verwendet daher size_t und verweist auf dieselbe stddef.h-Datei wie der Benutzercode.

  • Trotzdem fühlt es sich ziemlich seltsam an, dass ein eingebauter Operator sizeof ergibt einen Ausdruck eines Bibliothekstyps size_t. 🙂

    – musiphil

    10. April 2014 um 20:57 Uhr

  • @musiphil: Es könnte sich weniger seltsam anfühlen, es so zu sehen: Die Bibliothek muss definieren size_t der Typ zu sein, dass die sizeof Betreiber ergibt.

    – Michael Burr

    10. April 2014 um 21:24 Uhr

Aus MSDN:

Wenn der sizeof-Operator auf ein Objekt vom Typ char angewendet wird, ergibt dies 1

Selbst wenn Sie stddef.h nicht verfügbar/enthalten haben und size_t nicht kennen, können Sie mit sizeof die Größe von Objekten relativ zu char ermitteln.

  • Wenn Sie diese Größe jedoch irgendwo speichern möchten, ohne einen Überlauf zu riskieren, benötigen Sie die Typedef von size_t.

    anon

    11. April 2009 um 8:17 Uhr

  • schnaader: Alles, was sagt, ist, dass size_t eine Art ganzzahliger Typ sein wird, aber nicht genau welcher Typ.

    – Ashwin Nanjappa

    11. April 2009 um 9:09 Uhr

  • @Neil – Ehrlich gesagt, wie oft finden Sie einen Typ, für den sizeof() etwas zurückgibt, das sogar ein unsigned char überlaufen würde? Auf meinem System ist sogar eine FILE-Struktur nur 88 Bytes groß.

    – Chris Lutz

    12. April 2009 um 4:17 Uhr

1366320cookie-checkC: Warum ist size_t kein C-Schlüsselwort?

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

Privacy policy