Poradie kontrola podmienok v C

0

Otázka

Tak som čítal o poradí jednotlivých subjektov, a ja som čítal, že && má vyšší význam, ako || a to by hodnotila skôr (zdroj). Potom niekto otázku o tom, čo tento kus kódu bude tlače:

#include <stdio.h>
int main(){
    int a=0, b=0, c=0, d=0;
    if(a++>0 || ++b==1 || c--<=0 && d++>c--){
        printf("if\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    else{
        printf("else\na:%d\nb:%d\nc:%d\nd:%d\n",a,b,c,d);
    }
    return 0;
}

A ja som si myslel, že c-- <= 0 && d++ > c-- by vyhodnotiť ako prvý, čo je pravda, v celkom. po procese, c by byť rovná -2 a d by byť rovná 1. Potom by to spustiť kontrolu z ľavej strany, hodnotenie a++ > 0 || ++b == 1 čo je pravda, a by byť 1 na konci a b 1 v stave a po. takže celkový stav by byť true || true a je to pravda, tak budeme tlače:

if
a:1
b:1
c:-2
d:1

Áno? Zdá sa, že nie. Som vyskúšal s GCC (Mingw) na môj systém (Windows, 10), a s online prekladač (tento jeden) a oba vytlačené:

if
a:1
b:1
c:0
d:0

Som zmenil podmienku na to: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) ale výstup je presne tú istú vec, na oboch miestach. Je tam niečo, čo nechcem venovať pozornosť? Alebo je to niečo ako chyba? Takmer to vyzerá, že || a && majú rovnakú prioritu a celá vec je hodnotené z ľavej strany, a skratu, vyskytuje a iné veci. Ak by som zmeniť ++b==1 časť do ++b==0potom výstup je rovnaký, ako som predpovedal.
Vďaka vopred za akúkoľvek druh pomoci :)

1

Najlepšiu odpoveď

4

Výraz v tejto otázke:

if(a++>0 || ++b==1 || c--<=0 && d++>c--)

je klasickým príkladom hrozné, hrozné prejavu, odporne nereálne a nepraktické, a punishingly ťažké pochopiť, čo však robí dobrú prácu na ilustráciu super dôležitý bod: prednosť, nie je rovnaké ako poradie vyhodnocovania.

Čo prednosť naozaj nám je, ako prevádzkovateľom, sú zahnutý nahor s ich operandov. Tak vzhľadom zjednodušený výraz

A || B || C && D

ktoré dva subexpressions urobiť prvý ||a druhá ||a && skutočne kravatu spolu a pracovať na? Ak ste kompilátor spisovateľ, môžete odpovedať na tieto otázky stavbe "analyzovať strom", ktorý výslovne uvádza, ktoré subexpression(s) ísť s ktorou operátorov.

Takže, vzhľadom na termín A || B || C && D, má analyzovať strom na vyjadrenie vyzerať takto:

        &&
       /  \
     ||    D
    /  \
  ||    C
 /  \
A    B

alebo takto:

  ||
 /  \
A    ||
    /  \
   B    &&
       /  \
      C    D

alebo takto:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Ak chcete odpovedať na túto, potrebujeme vedieť nielen to, že prednosť && je vyššia ako ||,, ale aj to, že || je vľavo-asociatívne. Vzhľadom na tieto skutočnosti, výraz

A || B || C && D

je rozložený tak, ako keby to bolo písané

(A || B) || (C && D)

a preto výsledky v treťom z troch kandidátskych analyzovať stromy som ukázal:

      ||
     /  \
    /    \
  ||      &&
 /  \    /  \
A    B  C    D

Ale teraz sme v pozícii, aby naozaj videli, ako sa "skratom" správanie || a && prevádzkovatelia sa chystá uplatniť. Že "top" || je ísť na vyhodnotenie jej ľavej strane a potom, ak je nepravdivé, tiež vyhodnotiť pravej strane. Podobne nižšie || bude vyhodnotenie jeho ľavej strane. Takže, bez ohľadu na to, A bude dostať hodnotené ako prvý. Za prejav v pôvodnom otázku, ktorá zodpovedá a++ > 0.

Teraz, a++>0 je nepravdivé, takže budeme musieť vyhodnotiť B, ktoré je ++b == 1. Teraz, to je pravda, tak výsledkom prvej || je "pravda".

Takže výsledok druhej (top) || prevádzkovateľ je aj "pravda".

Tak na pravej strane hore || prevádzkovateľ nemusí byť zhodnotené vôbec.

Takže celý subexpression obsahujúce && nebudú posudzované na všetkých.

Takže aj keď && mal najvyššiu prioritu, sa skončil dostať za posledný, a (pretože veci na ľavej zapojené || a bola pravda) je to nie skončiť dostať zhodnotené vôbec.

Pointa, ako som začal tým, že hovorí, je, že prednosť neurčuje poradie vyhodnocovania.

Tiež, ak by to nebolo povedal inde, to zaručuje, left-to-right správanie je len garantovaná na || a && operátori (a, iným spôsobom, pre ternární ?: prevádzkovateľ). Ak výraz bol

A + B + C * D

to by nebol boli pravda, že, ako som už povedal skôr, "bez ohľadu na to, A bude dostať hodnotené prvý". Pre aritmetické operátory ako + a *neexistuje žiadny spôsob, ako vedieť, či ľavej alebo pravej strane sa chystá získať hodnotené ako prvý.

2021-11-24 12:41:40

Kompletné a Racionálne. Ďakujem veľmi pekne.
III_phr

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................