Hier ist der Code, der in Dev C ++ - Fenstern kompiliert wurde:
#include <stdio.h>
int main() {
int x = 5;
printf("%d and ", sizeof(x++)); // note 1
printf("%d\n", x); // note 2
return 0;
}
Ich erwarte x
6 nach Ausführung von Note 1 . Die Ausgabe lautet jedoch:
4 and 5
Kann jemand erklären, warum x
nicht nach Note 1 erhöht wird ?
VLAs
keiner der anderen dies tut.Antworten:
Aus dem C99 Standard (der Schwerpunkt liegt bei mir)
quelle
N
aus stdin und make lesenint array[N]
. Dies ist eine der C99-Funktionen, die in C ++ nicht verfügbar sind.sizeof(int[++x])
(wirklich, wirklich eine schlechte Idee, jedenfalls) das++
bewertet werden könnte.gcc
,clang
und bei ideone.com/Pf7iFsizeof
ist ein Operator zur Kompilierungszeit , daher werden zum Zeitpunkt der Kompilierungsizeof
und seines Operanden durch den Ergebniswert ersetzt. Der Operand wird überhaupt nicht ausgewertet (außer wenn es sich um ein Array mit variabler Länge handelt). Nur die Art des Ergebnisses ist von Bedeutung.Ausgabe:
as
short
belegt 2 Bytes auf meinem Computer.Ändern des Rückgabetyps der Funktion in
double
:wird
8
als Ausgabe geben.quelle
sizeof(foo)
versucht wirklich, die Größe eines Ausdrucks beim Kompilieren zu ermitteln:6.5.3.4:
Kurz gesagt: Arrays mit variabler Länge, die zur Laufzeit ausgeführt werden. (Hinweis: Arrays mit variabler Länge sind eine spezielle Funktion - keine Arrays, denen sie zugewiesen sind
malloc(3)
.) Andernfalls wird nur der Typ des Ausdrucks berechnet, und zwar zur Kompilierungszeit.quelle
sizeof
ist ein in die Kompilierungszeit eingebauter Operator und keine Funktion. Dies wird sehr deutlich, wenn Sie es ohne Klammern verwenden können:quelle
sizeof
Operator ist kein Operator zur Kompilierungszeit. Sie müssen ihm lediglich eine VLA geben, um dies herauszufinden.Hinweis
Diese Antwort wurde aus einem Duplikat zusammengeführt, das das späte Datum erklärt.
Original
Mit Ausnahme von Arrays mit variabler Länge wertet sizeof seine Argumente nicht aus. Wir können dies aus dem Entwurf des C99-Standardabschnitts
6.5.3.4
ersehen. Die Größe des Operators Absatz 2, der besagt:In einem Kommentar ( jetzt entfernt ) wurde gefragt, ob so etwas zur Laufzeit ausgewertet werden würde:
und in der Tat würde so etwas auch funktionieren ( beide live sehen ):
da sie beide Arrays variabler Länge sind. Obwohl ich in beiden Fällen nicht viel praktischen Nutzen sehe.
Beachten Sie , variabler Länge Arrays werden in der überdachten Entwurf C99 - Standard Abschnitt
6.7.5.2
Array Deklaratoren Absatz 4 :Aktualisieren
In C11 ändert sich die Antwort für den VLA-Fall. In bestimmten Fällen ist nicht angegeben, ob der Größenausdruck ausgewertet wird oder nicht. Aus dem Abschnitt
6.7.6.2
Array-Deklaratoren, der besagt:Zum Beispiel in einem Fall wie diesem ( live sehen ):
quelle
sizeof
ein Makro handelt - es erstellt keinen Code, sondern berechnet den erwarteten Wert vor und legt ihn direkt im Code ab. Beachten Sie, dass dies das einzige Verhalten bis C99 war, da es keine VBAs gab (ich hatte bis zu dieser Antwort noch nie davon gehört, ob Sie es glauben oder nicht!)sizeof (char[x++]);
der Wert vonx
für etwas anderes verwendet, als den Wert des Ausdrucksx++
und den neuen Wert für zu bestimmenx
, die beide bei diesem Operator normal sind?char[x++]
es sich um eine VLA handelt. es siehtchar*
für meine unbekannten Augen effektiv aus wie ein .Da der Operand des
sizeof
Operators nicht ausgewertet wird, können Sie Folgendes tun:Online-Demo: http://ideone.com/S8e2Y
Das heißt, Sie müssen die Funktion nicht definieren,
f
wenn siesizeof
nur in verwendet wird. Diese Technik wird hauptsächlich bei der Metaprogrammierung von C ++ - Vorlagen verwendet, da selbst in C ++ der Operand vonsizeof
nicht ausgewertet wird.Warum funktioniert das? Es funktioniert, weil der
sizeof
Operator nicht mit dem Wert arbeitet , sondern mit dem Typ des Ausdrucks. Wenn Sie also schreibensizeof(f())
, arbeitet es mit dem Typ des Ausdrucksf()
, der nichts anderes als der Rückgabetyp der Funktion istf
. Der Rückgabetyp ist immer derselbe, unabhängig davon, welchen Wert die Funktion zurückgeben würde, wenn sie tatsächlich ausgeführt wird.In C ++ können Sie sogar Folgendes tun:
Es sieht jedoch so aus
sizeof
, als würde ich zuerst eine Instanz von erstellenA
, indem ich schreibeA()
und dann die Funktionf
für die Instanz aufrufe, indem ich schreibeA().f()
, aber so etwas passiert nicht.Demo: http://ideone.com/egPMi
Hier ist ein weiteres Thema, das einige andere interessante Eigenschaften von erklärt
sizeof
:quelle
Die Ausführung kann während der Kompilierung nicht erfolgen. Also
++i
/i++
wird nicht passieren. Auchsizeof(foo())
nicht die Funktion ausführen , aber richtige Art zurück.quelle
sizeof
ist ein konstanter Ausdruck zur Kompilierungszeit"?sizeof
wird zur Kompilierungszeit ausgeführt,x++
kann jedoch nur zur Laufzeit ausgewertet werden. Um dies zu lösen, schreibt der C ++ - Standard vor, dass der Operand vonsizeof
nicht ausgewertet wird. Der C-Standard sagt:quelle
sizeof()
Der Operator gibt nur die Größe des Datentyps an und wertet keine inneren Elemente aus.quelle
sizeof()
Operator handelt rekursiv und erhält die Größe aller Elemente eines Containers, der Mitglieder einer Klasse oder Struktur usw. in Byte. Sie können dies sehr einfach selbst beweisen, indem Sie eine einfache Klasse mit wenigen Mitgliedern und erstellen aufrufensizeof()
. (Alles dort, was ein Zeiger ist, kann jedoch nicht die Größe von - nur die Größe des Zeigers - sehen.) Dies geschieht alles zur Kompilierungszeit, wie andere Kommentatoren angegeben haben: Ausdrücke innerhalb des Zeigers werdensizeof()
nicht ausgewertet.