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:
    4

    Eine Verständnisfrage hätte ich bezüglich der Reihenfolge
    der Ausführung der Auswertungen!
    Prinzipiell hätte ich die Ausgabe
    54

    erwartet.
    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 angibst

    printf("%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.


Anmelden zum Antworten