Warum wird nicht auch 5 ausgegeben?
-
[code="c"]
#include <stdio.h>int main(){
printf("%d", sizeof(printf("%d", 5)));
getchar();
return 0;
}
[/c]Mit MSVC kompiliert wird dabei ausgegeben:
4Eine Verständnisfrage hätte ich bezüglich der Reihenfolge
der Ausführung der Auswertungen!
Prinzipiell hätte ich die Ausgabe
54erwartet.
Erstmal müssten doch beide Parameter des 'äußeren' printf() Ausdrucks
ausgewertet werden, vor dem nächsten 'Sequence Point' (laut C-Standard).
Um das zu tun, muss zuerst das 'innere' printf() ausgewertet werden, weil
es int zurückgibt sollte sizeof() eigentlich schon zur Compile-Zeit wissen,
dass die Größe des zurückgegebenen Typs '4' ist.
Einzig das Ausbleiben des Seiteneffekts der 'inneren' printf()
Aufrufung im ausgeführten Programm, nämlich auch die Ausgabe von '5',
unterbleibt seltsamer weise!Das Beispiel ist jetzt nur konstruiert, weil ich mir darüber im Klaren sein
will, wohin und warum die Ausgabe des 'inneren' printf() verschwindet ?
Weil rein syntaktisch als auch semantisch
ist das printf()-Statement meiner Meinung nach unmissverständlich, oder nicht?
Oder ist undefined behaviour auch laut Standard zu erwarten?mfg
-
The sizeof operator
...The size is determined from the type of
the operand ....ist das gleiche in grün wie
printf("%d", sizeof(88));
-
#include <stdio.h> int main(){ printf("%d", sizeof(printf("%d", 5))); getchar(); return 0; }
Undefined behaviour?
Beim gründlichen Durchlesen des C-Standards staune ich immer wieder, was
alles zu undefined behaviour führen darf und kann. Theoretisch und laut
C-Standard dürfte die 'abstrakte C-Maschine' bei jedem Integer Overflow damit
beginnen, die Festplatte zu formatieren ('undefined behaviour', alles ist
möglich).
Also ich stelle es mir ziemlich unmöglich vor, auch nur eine mehr als
10-zeilige C-Funktion zu schreiben, für die man zu 100% ein definiertes
(determiniertes) Verhalten im Rahmen des C-Standards vorhersagen könnte.
Praktisch jede Fließkomma-Rechnung -> undefined behaviour.
Triviale Sachen wie Bitschiebe-Operationen, Anwendung des unären - Operators
auf INT_MIN usw. -> alles undefined behaviour.
Da müsste man schon extrem umständlichen C-Code schreiben, um jedes auf irgend-
einer exotischen Maschine ablaufende Programm berechenbar zu halten und
undefined behaviour bei 11-bit-pro Byte Rechnern mit Fließkomma-Formaten
von völlig willkürlicher Beschaffenheit zu umgehen.
Oder kennt Ihr auch längere Programme, die auf wirklich jeder hypothetischen
'abstrakten' und standardkonformen C-Maschine ein vorhersagbares Verhalten
an den Tag legen müssten?
mfg
-
Nö, nicht undefined, es wird sizeof(int) ausgegeben.
-
Der Operand von sizeof wird nicht ausgeführt. Der ganze Ausdruck sizeof(printf("%d", 5)) wird zur Compilezeit durch die Größe eines ints ersetzt (des Rückgabetyps von printf), und zur Laufzeit findet da gar nichts mehr statt.
-
Nikolaus6 schrieb:
Also ich stelle es mir ziemlich unmöglich vor, auch nur eine mehr als
10-zeilige C-Funktion zu schreiben, für die man zu 100% ein definiertes
(determiniertes) Verhalten im Rahmen des C-Standards vorhersagen könnte.Mit anderen Worten: Du kannst dir nicht vorstellen, dass der C-Standard in irgendeiner Form von praktischer Relevanz ist!?
Nikolaus6 schrieb:
Praktisch jede Fließkomma-Rechnung -> undefined behaviour.
Triviale Sachen wie Bitschiebe-Operationen, Anwendung des unären - Operators
auf INT_MIN usw. -> alles undefined behaviour.Wie kommst du drauf?
-
Der Operand des sizeof Operators wird prinzipiell nicht evaluiert, der Operand muss ein konstanter Ausdruck sein, deshalb kommt es nicht zum Funktionsaufruf.
Ein Funktionsaufruf ist ein Ausdruck, hat also Typ und Wert.
Zur Compilezeit kann der Wert des Ausdrucks Funktionsaufruf nicht ermittelt werden, außerdem muss er ja konstant sein, und der Typ des Funktionsaufrufes (nicht der Funktion!) ist der deklarierte Rückgabewert der Funktion.
Interessant dürfte eine void-Funktion sein, also forsche mal weiter.
Aber trotzdem hast du UB, da sizeof size_t liefert, und "%d" nicht dazu passt.
Wenn du statt eines Funktionsaufrufes die Funktion selbst angibstprintf("%d",(int)sizeof printf);
hast du kein UB vorliegen, sondern eine constraint violation, d.h. der Compiler muss hierbei irgendwas melden; hierbei zerfällt der Funktionsname per Definition nicht in einen Zeiger auf die Funktion, die Größe eines Funktionszeigers ist (standardkonform) bestimmbar, die Größe einer Funktion selbst nicht.