Cílem kontroly podmínek v C

0

Otázka

Tak jsem četl o zájmu různých subjektů, a četl jsem, že && má vyšší význam než || a to by vyhodnotit dříve (zdroj). Pak se někdo zeptal na otázku o tom, co tento kus kódu by tisk:

#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 já si myslel, že c-- <= 0 && d++ > c-- by vyhodnotit jako první, což je pravda v celkem. po procesu, c bude se to rovnat -2 a d bude se to rovnat 1. Pak to začne kontrolu z levé strany, hodnocení a++ > 0 || ++b == 1 což je pravda, a by 1 na konci a b 1 ve stavu a po. takže celkový stav by měl být true || true a je to pravda, tak se vypíše:

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

Ano? Zdá se, že ne. Testoval jsem to s GCC (Mingw) na můj systém (Windows 10), a s on-line compiler (tenhle) a tištěné:

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

Jsem se změnil stav na toto: if(a++>0 || ++b==1 || (c--<=0 && d++>c--) ) ale výstup je stejné na obou místech. Je tam něco, co já ne věnovat pozornost? Nebo je to něco jako chyba? Skoro to vypadá, že || a && mají stejnou prioritu a celá věc je hodnocen z levé strany, a krátký-obvodů se vyskytuje a další věci. Pokud změním ++b==1 součástí do ++b==0, pak na výstupu je stejné jak jsem předpovídal.
Díky předem za jakoukoliv pomoc :)

1

Nejlepší odpověď

4

Vyjádření v této otázce:

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

je to klasický příklad hrozný, hrozný výraz, neskutečně nereálné a nepraktické, a mučivě obtížné pochopit, což však dělá dobrou práci, což dokládá mimořádně důležitý bod: pořadí není stejné jako pořadí hodnocení.

Co přednost nám skutečně říká, je to, jak operátoři mají co do činění s jejich operandy. Takže vzhledem k tomu, že zjednodušený výraz

A || B || C && D

které dvě seskupení udělat první ||a druhá ||a && vlastně svázat dohromady a provozovat na? Pokud jste kompilátor spisovatel, odpovědět na tyto otázky tím, že postaví "analyzovat strom", která jednoznačně ukazuje, která zrušila(y), jít s nimiž operátory.

Takže, vzhledem k tomu, výraz A || B || C && Dmá derivační strom pro výraz vypadat takto:

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

nebo takhle:

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

nebo takhle:

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

Abychom mohli odpovědět, musíme vědět, nejen to, že přednost && je vyšší než ||, ale také to, že || zbývá-asociativní. Vzhledem k těmto skutečnostem, výraz

A || B || C && D

je analyzován jako kdyby to bylo napsáno

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

a proto výsledky ve třetím ze tří kandidátských analyzovat stromy ukázal jsem:

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

Ale teď jsme v pozici, aby skutečně vidět, jak "zkratem" chování || a && provozovatelé je budou aplikovat. To, že "top" || bude hodnotit jeho levé straně, a pak, pokud je to falešný, také hodnotit pravé straně. Podobně, dolní || bude hodnotit jeho levé straně. Takže, bez ohledu na to, co, A bude vyhodnocen jako první. Pro vyjádření v původní otázce, která odpovídá a++ > 0.

Teď a++>0 je false, takže to budeme muset vyhodnotit B, který je ++b == 1. Nyní, to je pravda, tak výsledek první || je "pravda".

Takže výsledek druhé (horní) || provozovatel je také "pravda".

Takže na pravé straně horní || provozovatel nemusí být vůbec hodnoceny.

Takže celé seskupení obsahující && nebudou hodnoceny vůbec.

Takže i když && měl nejvyšší přednost, to skončilo za poslední, a (od věci k levé zapojeni || a byla to pravda) to není nakonec vůbec hodnoceny.

Sečteno a podtrženo, jak jsem začal tím, že říká, že přednost neurčuje pořadí hodnocení.

Také, pokud nebyl to řekl jinde, je to garantované, vlevo-k-pravý chování je pouze garantované pro || a && operátory (and, jiným způsobem, pro ternární ?: operátor). Pokud výraz byl

A + B + C * D

to by neměla být pravda, že, jak jsem již uvedl, "bez ohledu na to, A bude vyhodnocen na prvním místě". Pro aritmetické operátory jako + a *, tam je žádný způsob, jak vědět, zda levé nebo pravé straně bude vyhodnocen jako první.

2021-11-24 12:41:40

Kompletní a Racionální. Ještě jednou díky moc.
III_phr

V jiných jazycích

Tato stránka je v jiných jazycích

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