Valore in Output differente da quello aspettato

di il
21 risposte

21 Risposte - Pagina 2

  • Re: Valore in Output differente da quello aspettato

    
        19: 	int c = ++a + fun(a);
    003B182C 8B 45 F8             mov         eax,dword ptr [a]  
    003B182F 83 C0 01             add         eax,1  
    003B1832 89 45 F8             mov         dword ptr [a],eax  
    
    003B1835 8B 4D F8             mov         ecx,dword ptr [a]  
    003B1838 51                   push        ecx  
    003B1839 E8 8E F9 FF FF       call        fun (03B11CCh)  
    003B183E 83 C4 04             add         esp,4  
    
    003B1841 03 45 F8             add         eax,dword ptr [a]  
    
    003B1844 89 45 E0             mov         dword ptr [c],eax  
    
    ...
    
        22: 	int d = fun(b) + ++b;
    003B1858 8B 45 EC             mov         eax,dword ptr [b]  
    003B185B 83 C0 01             add         eax,1  
    003B185E 89 45 EC             mov         dword ptr [b],eax  
    
    003B1861 8B 4D EC             mov         ecx,dword ptr [b]  
    003B1864 51                   push        ecx  
    003B1865 E8 62 F9 FF FF       call        fun (03B11CCh)  
    003B186A 83 C4 04             add         esp,4  
    
    003B186D 03 45 EC             add         eax,dword ptr [b]  
    
    003B1870 89 45 D4             mov         dword ptr [d],eax  
    
    Buonanotte
    Allegati:
    9500_6dfa6fb1334f42ad09e14eefbde429e9.jpg
    9500_6dfa6fb1334f42ad09e14eefbde429e9.jpg
  • Re: Valore in Output differente da quello aspettato

    Buongiorno!
    Scusa, ma non conosco l'assembly. In ogni caso stando alla tua precedente interpretazione del concetto di precedenza applicato alla chiamata a funzione dovrebbe essere sì c=d, ma c=d=7, o sbaglio?
    Dalle poche prove effettuate mi sembra che gcc avanza sempre da sinistra a destra, mentre VC non segue una regola precisa in questo senso, anzi sembra dare la priorità all'operatore di incremento prefisso rispetto alla chiamata a funzione, anche se la tabella delle precedenze dice l'esatto opposto.
  • Re: Valore in Output differente da quello aspettato

    Il fatto è che le tue righe di codice producono un undefined behaviour quindi il compilatore può dare il risultato che vuole.
    Vedi:
    https://stackoverflow.com/questions/33629617/c-operator-precedence-gcc-5-2-vs-visual-studio-2015
    https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points
    https://stackoverflow.com/questions/3457967/what-belongs-in-an-educational-tool-to-demonstrate-the-unwarranted-assumptions-pe/3458842#3458842
    https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points/4183735#4183735

    Per quanto riguarda il famoso 22/11 * 2, il mio era un discorso trascendente il C/C++ o altri linguaggi e voleva solo evidenziare come anche gli umani che non conoscono le regole PEMDAS della matematica possono essere messe in difficoltà. Non a caso l'ho definito un "giochino".
    Vedi:
    http://blogdimatematicaescienze.it/il-paradosso-del-pemdas-lavete-risolto/
  • Re: Valore in Output differente da quello aspettato

    Nippolo ha scritto:


    Scusa, ma non conosco l'assembly
    E' evidente quello che fa il compilatore ... non bisogna conoscere l'assembly ...
    L'operatore di incremento viene "comunque" eseguito prima della chiamata a funzione, sia che stia a sinistra, sia che stia a destra (ovviamente in assenza di parentesi che modifichino la priorità).
    mentre VC non segue una regola precisa in questo senso, anzi sembra dare la priorità all'operatore di incremento prefisso rispetto alla chiamata a funzione, anche se la tabella delle precedenze dice l'esatto opposto.
    "Non segue una regola"? "Esatto opposto"? Veramente nella tabella proprio l'operatore di incremento pre/post è indicato con priorità maggiore rispetto alla chiamata di funzione, cosa che è rispettata nel "tuo" esempio ... (quello che ho detto prima, per la chiamata alla funzione, per l'espressione dell'op, quindi continua ad essere corretto)
    ++ -- Suffix/postfix increment and decrement
    () Function call
    [] Array subscripting
    . Structure and union member access
    -> Structure and union member access through pointer
    (type){list} Compound literal(C99)
    quindi non capisco questa tua precisazione. Anzi, comincio a non capire questa tua "battaglia" ... A me sembra tutto chiaro.
  • Re: Valore in Output differente da quello aspettato

    shodan ha scritto:


    Il fatto è che le tue righe di codice producono un undefined behaviour quindi il compilatore può dare il risultato che vuole.
    Vedi:
    https://stackoverflow.com/questions/33629617/c-operator-precedence-gcc-5-2-vs-visual-studio-2015
    https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points
    https://stackoverflow.com/questions/3457967/what-belongs-in-an-educational-tool-to-demonstrate-the-unwarranted-assumptions-pe/3458842#3458842
    https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points/4183735#4183735
    ...
    La questione non è proprio semplicissima, in ogni caso grazie per i link, approfondirò!

    oregon ha scritto:


    ...
    mentre VC non segue una regola precisa in questo senso, anzi sembra dare la priorità all'operatore di incremento prefisso rispetto alla chiamata a funzione, anche se la tabella delle precedenze dice l'esatto opposto.
    "Non segue una regola"? "Esatto opposto"? Veramente nella tabella proprio l'operatore di incremento pre/post è indicato con priorità maggiore rispetto alla chiamata di funzione, cosa che è rispettata nel "tuo" esempio ... (quello che ho detto prima, per la chiamata alla funzione, per l'espressione dell'op, quindi continua ad essere corretto)
    ++ -- Suffix/postfix increment and decrement
    () Function call
    [] Array subscripting
    . Structure and union member access
    -> Structure and union member access through pointer
    (type){list} Compound literal(C99)
    ...
    Scusa ma come la leggi la tabella?! Io vedo che la chiamata a funzione ha la stessa precedenza dell'incremento suffisso (o postfisso che dir si voglia), mentre ha una precedenza maggiore rispetto all'incremento prefisso. Quindi stando al tuo ragionamento l'output sarebbe dovuto essere c=d=7.
    In ogni caso continuo a sospettare che la precedenza nulla c'entri né col mio esempio né con quello dell'op. Le regole di precedenza/associatività si limitano a definire il raggruppamento dell'espressione in sotto-espressioni, ma nulla ci dicono sull'ordine in cui le sotto-espressioni e/o i singoli operandi vengono valutati. Sbaglio?
    Per esempio considerando la seguente espressione
    int a = fun() + !n;
    siamo proprio sicuri che le regole di precedenza ci assicurano che il primo addendo sia valutato prima del secondo?
  • Re: Valore in Output differente da quello aspettato

    Come riportato in

    https://northstar-www.dartmouth.edu/doc/ibmcxx/en_US/doc/language/concepts/cuexppre.htm

    "Special Cases
    Order of evaluation for function call arguments or for the operands of binary operators is not specified. Avoid writing ambiguous expressions, such as:

    z = (x * ++y) / func1(y);
    func2(++i, x);

    In the example above, the order of evaluation of ++y and func1(y) is not defined. In fact, they might not even be evaluated in the same order at different optimization levels. Do not write code that depends on a particular order of evaluation of operators that have the same precedence.
    "

    direi che la questione (tra priority e associativity) è, in molti casi, indefinita e ogni compilatore si comporta in modo diverso.

    L'unica difesa è, appunto, la scrittura di espressioni chiare, con qualche parentesi in più o spezzata in sotto-espressioni più semplici.

    Saluti a tutti
  • Re: Valore in Output differente da quello aspettato

    Nippolo ha scritto:


    Riguardo invece alla maggiore affidabilità di VC sottolineata da te e @oregon ho qualche dubbio, nel senso che non sono tanto sicuro che il concetto di precedenza applicato alla chiamata a funzione sia quello da voi ipotizzato.

    Nippolo ha scritto:


    In ogni caso continuo a sospettare che la precedenza nulla c'entri né col mio esempio né con quello dell'op. Le regole di precedenza/associatività si limitano a definire il raggruppamento dell'espressione in sotto-espressioni, ma nulla ci dicono sull'ordine in cui le sotto-espressioni e/o i singoli operandi vengono valutati.
    La mia quindi non era una "battaglia" contro i mulini a vento!

    oregon ha scritto:


    direi che la questione (tra priority e associativity) è, in molti casi, indefinita e ogni compilatore si comporta in modo diverso.
    Le regole di precedenza e associatività sono ben definite, è l'ordine di valutazione ad essere indefinito, a meno che si tratti di un'espressione logica, in quel caso infatti per rispettare la valutazione a corto-circuito si avanza sempre da sinistra verso destra.

    Per quanto riguarda invece la questione della tabella, hai preso tu una svista o mi sono perso io qualcosa?
Devi accedere o registrarti per scrivere nel forum
21 risposte