Warum ist die Größe einer Funktion in C immer 1 Byte?

Lesezeit: 5 Minuten

Benutzeravatar von user1645461
Benutzer1645461

Wenn wir die Größe einer Funktion mit überprüfen sizeof()bekommen wir immer 1 Byte. Was bedeutet dieses 1 Byte?

Benutzeravatar von Kerrek SB
Kerrek SB

Es ist eine Einschränkungsverletzung und Ihr Compiler sollte diagnostizieren. Wenn es trotzdem kompiliert wird, hat Ihr Programm ein undefiniertes Verhalten [thanks to @Steve Jessop for the clarification of the failure mode, and see @Michael Burr’s answer for why some compilers allow this]: Ab C11, 6.5.3.4./1:

Das sizeof -Operator darf nicht auf einen Ausdruck mit Funktionstyp angewendet werden

  • Das ist eine Einschränkung, was bedeutet, dass sie in einem konformen Compiler diagnostiziert wird. Wenn der Compiler es trotzdem kompiliert (nachdem er es diagnostiziert hat), ist das Verhalten undefiniert. Wenn der Compiler es nicht diagnostiziert (was zum Beispiel gcc nicht ohne -pedantic), haben Sie einen nicht konformen Compiler und jeder Programm hat undefiniertes Verhalten.

    – Steve Jessop

    4. September 2012 um 9:46 Uhr


  • Das Verhalten stellt es in die gleiche Kategorie wie eine GNU C-Erweiterung, aber ich habe keine Ahnung, warum irgendjemand will dieses Verhalten, also weiß ich nicht, warum die GNU-Autoren sich die Mühe gemacht haben, es hinzuzufügen.

    – Steve Jessop

    4. September 2012 um 9:49 Uhr


  • @SteveJessop: Beachten Sie, dass dies sogar mit ist -std=c11, nicht gnu11. Dies ist eine wirklich seltsame Compiler-Erweiterung.

    – Kerrek SB

    4. September 2012 um 9:50 Uhr

  • Oh! Ich wette, es geht darum, Arithmetik für Funktionszeiger zu aktivieren, genauso wie das sizeof(void) ist 1 in GNU C.

    – Steve Jessop

    4. September 2012 um 9:52 Uhr


  • Bezüglich -std=c11: jemand sollte die beziehen -std=c* Optionen zu Werbestandards. Sie aktivieren keinen Konformitätsmodus, sie deaktivieren lediglich Erweiterungen, die verhindern würden, dass ein wohlgeformtes Programm kompiliert wird (wie z typeof ein Schlüsselwort sein, da ein wohlgeformtes C-Programm es als Variablennamen verwenden kann, aber gcc würde das standardmäßig ablehnen). Um zusätzlich Erweiterungen zu deaktivieren, mit denen fehlerhafte Programme nicht diagnostiziert werden können, benötigen Sie -pedantic oder -pedantic-errors.

    – Steve Jessop

    4. September 2012 um 9:58 Uhr


Dies ist kein undefiniertes Verhalten – der C-Sprachstandard erfordert eine Diagnose bei der Verwendung von sizeof -Operator mit einem Funktionsbezeichner (einem Funktionsnamen), da es sich um eine Einschränkungsverletzung für die handelt sizeof Operator.

Als Erweiterung der C-Sprache erlaubt GCC jedoch Arithmetik void Zeiger und Funktionszeiger, was durch Behandlung der Größe von a erreicht wird void oder eine Funktion als 1. Als Folge davon ist die sizeof Betreiber wird zu evaluieren 1 zum void oder eine Funktion mit GCC. Sehen http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith

Sie können GCC veranlassen, bei der Verwendung eine Warnung auszugeben sizeof mit diesen Operanden, indem Sie die verwenden -pedantic oder -Wpointer-arith Optionen zu GCC. Oder machen Sie einen Fehler mit -Werror=pointer-arith.

  • Deine Logik ist fehlerhaft. C benötigt Diagnosemeldungen für einige, aber nicht alle UB. Sie können nicht sagen, dass etwas definiertes Verhalten hat, nur weil es eine Diagnose gibt.

    – MSalter

    4. September 2012 um 9:05 Uhr

  • C erfordert eine Diagnose für alle Beschränkungsverletzungen (5.1.1.3 Diagnose in C99 oder C11). Eine Einschränkung (3.8 in C99/C11) ist eine “Einschränkung, entweder syntaktisch oder semantisch, durch die die Darstellung von Sprachelementen interpretiert werden soll”, was zu sagen scheint, dass etwas, das den Einschränkungen nicht folgt, nicht interpretiert werden kann .

    – Michael Burr

    4. September 2012 um 9:13 Uhr

  • Und um es klar zu sagen – eine Einschränkungsverletzung führt nicht zu undefiniertem Verhalten. Es ist ein Fehler, wie ein Syntaxfehler. Zum Beispiel sagt der Standard, „wenn eine „soll“- oder „soll nicht“-Anforderung erscheint außerhalb einer Beschränkung verletzt wird, ist das Verhalten undefiniert”. Wenn eine Einschränkungsverletzung zu UB führen würde, warum würde der Standard dann nur über die “sollte” und “sollte nicht” sprechen, die hier nicht in den Einschränkungen enthalten sind?

    – Michael Burr

    4. September 2012 um 9:27 Uhr

  • Ich habe wirklich nicht viel über UB gesagt, außer das sizeof Eine Funktion ist nicht UB (was ich ziemlich nur erwähnt habe, weil andere Antworten angegeben haben, dass es UB war). Aber vielleicht habe ich das durch die Art und Weise, wie ich den Satz aufgebaut habe, durcheinander gebracht. Um klarer zu sein. sizeof Eine Funktion ist nicht UB (wie mehrere Antworten behauptet haben). Es handelt sich um eine Einschränkungsverletzung. Als solches erfordert es eine Diagnose. GCC lässt es als Erweiterung zu.

    – Michael Burr

    4. September 2012 um 9:50 Uhr

  • @KerrekSB: Das OP erhält keine Diagnose, da es vermutlich GCC verwendet, was diese Verwendung als C-Spracherweiterung zulässt.

    – Michael Burr

    4. September 2012 um 9:52 Uhr


Es bedeutet, dass der Compiler-Autor sich für einen Wert von 1 entschieden hat, anstatt Dämonen aus Ihrer Nase fliegen zu lassen (in der Tat war dies eine weitere undefinierte Verwendung von sizeof das gab uns diesen Ausdruck: “Der C-Compiler selbst MUSS eine Diagnose ausgeben, WENN dies die erste erforderliche Diagnose ist, die sich aus Ihrem Programm ergibt, und kann dann selbst Dämonen dazu bringen, aus Ihrer Nase zu fliegen (was übrigens gut dokumentiert sein könnte Diagnosenachricht), genauso wie es weitere Diagnosen für weitere Verletzungen von Syntaxregeln oder -einschränkungen ausgeben KANN (oder aus irgendeinem Grund, den es wählt).” https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J

Daraus ergibt sich der umgangssprachliche Begriff „nasale Dämonen“ für alles, was ein Compiler als Reaktion auf ein undefiniertes Konstrukt zu tun beschließt. 1 ist der nasale Dämon dieses Compilers für diesen Fall.

  • @IlmariKaronen Ich muss jedoch zugeben, dass es einen Grund gibt, warum die meisten meiner Antworten zu C (und C ++) entweder auf allgemeinen sprachagnostischen Prinzipien oder solchen historischen Nuggets beruhen. Meine C-Erfahrung grenzt an sich schon an historisch 🙂

    – Jon Hanna

    4. September 2012 um 22:51 Uhr

Wie andere darauf hingewiesen haben, kann sizeof() jeden gültigen Bezeichner annehmen, gibt jedoch kein gültiges (ein ehrlich wahres und gültiges) Ergebnis für Funktionsnamen zurück. Darüber hinaus kann es definitiv zu einem „Dämonen-aus-der-Nasen“-Syndrom führen oder auch nicht.

Wenn Sie die Größe Ihrer Programmfunktion profilieren möchten, überprüfen Sie die Linker-Map, die sich im Zwischenergebnisverzeichnis befindet (dasjenige, in dem Dinge in .obj/.o kompiliert werden oder in dem das resultierende Bild/die ausführbare Datei liegt). Manchmal gibt es eine Option, diese Zuordnungsdatei zu generieren oder nicht … sie ist vom Compiler/Linker abhängig.

Wenn Sie die Größe eines Zeigers auf eine Funktion haben wollten, haben sie alle die gleiche Größe, die Größe eines Adressierungsworts auf Ihrer CPU.

1419830cookie-checkWarum ist die Größe einer Funktion in C immer 1 Byte?

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

Privacy policy