Wenn wir die Größe einer Funktion mit überprüfen sizeof()
, erhalten wir immer 1 Byte . Was bedeutet dieses 1 Byte?
87
Es ist eine Beschränkung verletzt, und der Compiler sollte es diagnostizieren. Wenn es es trotzdem kompiliert, hat Ihr Programm ein undefiniertes Verhalten [danke an @Steve Jessop für die Klärung des Fehlermodus und siehe @ Michael Burrs Antwort, warum einige Compiler dies zulassen]: Ab C11, 6.5.3.4./ 1:
Der
sizeof
Operator darf nicht auf einen Ausdruck mit Funktionstyp angewendet werden
-pedantic
), haben Sie einen nicht konformen Compiler und jedes Programm hat ein undefiniertes Verhalten.-std=c11
, nichtgnu11
. Dies ist eine wirklich seltsame Compiler-Erweiterung.sizeof(void)
1 in GNU C.-std=c11
: Jemand sollte die-std=c*
Optionen auf Werbestandards verweisen . Sie aktivieren den Konformitätsmodus nicht, sondern deaktivieren lediglich Erweiterungen, die das Kompilieren eines wohlgeformten Programms verhindern würden (z. B.typeof
ein Schlüsselwort, da ein wohlgeformtes C-Programm es als Variablennamen verwenden kann, dies jedochgcc
standardmäßig ablehnen würde ). Um Erweiterungen zusätzlich zu deaktivieren, die es schlecht geformten Programmen ermöglichen, nicht diagnostiziert zu werden, benötigen Sie-pedantic
oder-pedantic-errors
.Dies ist kein undefiniertes Verhalten. Der C-Sprachstandard erfordert eine Diagnose, wenn der
sizeof
Operator mit einem Funktionsbezeichner (einem Funktionsnamen) verwendet wird, da dies eine Einschränkungsverletzung für densizeof
Operator darstellt.Als Erweiterung der C-Sprache ermöglicht GCC jedoch die Arithmetik von
void
Zeigern und Funktionszeigern, indem die Größe einervoid
oder einer Funktion als behandelt wird1
. Infolgedessensizeof
bewertet der Bediener1
fürvoid
oder eine Funktion mit GCC. Siehe http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-ArithSie können GCC veranlassen, bei Verwendung
sizeof
mit diesen Operanden eine Warnung auszugeben, indem Sie die Optionen-pedantic
oder-Wpointer-arith
für GCC verwenden. Oder machen Sie einen Fehler mit-Werror=pointer-arith
.quelle
sizeof
gesagt, außer dass eine Funktion nicht UB ist (was ich so ziemlich nur erwähnte, weil andere Antworten besagten, dass es UB war). Aber vielleicht habe ich das durcheinander gebracht, weil ich den Satz so strukturiert habe. Um klarer zu sein.sizeof
Eine Funktion ist nicht UB (wie mehrere Antworten behauptet haben). Es ist eine Einschränkungsverletzung. Daher ist eine Diagnose erforderlich. GCC erlaubt es als Erweiterung.Dies bedeutet, dass der Compiler-Writer sich für einen Wert von 1 entschieden hat, anstatt Dämonen aus der Nase fliegen zu lassen (tatsächlich war es eine andere undefinierte Verwendung
sizeof
, die uns diesen Ausdruck gab: "Der C-Compiler selbst MUSS eine Diagnose ausgeben, wenn dies die erste erforderliche ist Eine Diagnose, die sich aus Ihrem Programm ergibt und dann möglicherweise selbst dazu führt, dass Dämonen aus Ihrer Nase fliegen (was übrigens durchaus die dokumentierte Diagnosemeldung sein könnte), genauso wie sie möglicherweise eine weitere Diagnose für weitere Verstöße gegen Syntaxregeln oder -beschränkungen (oder aus irgendeinem Grund, den es wählt). " https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8JDaraus ergibt sich die umgangssprachliche Bezeichnung "Nasendämonen" für alles, was ein Compiler als Reaktion auf ein undefiniertes Konstrukt tun möchte.
1
ist der Nasendämon dieses Compilers für diesen Fall.quelle
Wie andere betonten, kann sizeof () einen beliebigen gültigen Bezeichner annehmen, gibt jedoch kein gültiges (ehrlich wahres und gültiges) Ergebnis für Funktionsnamen zurück. Darüber hinaus kann es definitiv zu einem "Dämonen aus der Nase" -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 Verzeichnis der Zwischenergebnisse befindet (das Verzeichnis, in dem die Dinge in .obj / .o kompiliert werden oder in dem das resultierende Image / die ausführbare Datei abgelegt ist). Manchmal gibt es eine Option, um diese Map-Datei zu generieren oder nicht ... sie ist vom Compiler / Linker abhängig.
Wenn Sie die Größe eines Zeigers auf eine Funktion haben möchten, haben sie alle die gleiche Größe, die Größe eines Adressierungsworts auf Ihrer CPU.
quelle
int x = 1;
aber nur einer davon ist für einen standardkonformen Compiler zulässig. Wennsizeof()
es auf eine Funktion angewendet wird, kann es einen festgelegten Wert zurückgeben oder nicht oder die Kompilierung verweigern oder einen zufälligen Wert zurückgeben, der auf dem basiert, was sich zu diesem Zeitpunkt in einem bestimmten Register befindet. Buchstäbliche Nasendämonen sind unwahrscheinlich, liegen jedoch im Rahmen des Standards.sizeof
auf einen Zeiger auf eine Funktion an.