Hlavnφ
Hlavnφ strana
Seznam Φlßnk∙
NejΦten∞jÜφ Φlßnky
Progres e-mailem
Visual C++ FAQ

banner1.gif (2545 bytes)

Serißly
COM
ISAPI

Nenechte si ujφt
NeobdΘlnφkovß okna
Tisk bez Preview
MFC a DLL
Logo v MDI ploÜe
Kouzla s kombo-boxem
V²jimky v C++

banner.gif (3305 bytes)

LogickΘ v²razy a jazyk C/C++ Radek Paviensk²
11.11.1999
[Hlavnφ strßnka]  |  [Rubrika]

Jazyk C pou₧φvß pro vyhodnocenφ logick²ch operßtor∙ tzv. lenivΘ vyhodnocovßnφ, co₧ znamenß, ₧e se vyhodnotφ jen nejnutn∞jÜφ Φßst logickΘho v²razu.

Pokud mßme nap°φklad logick² v²raz

1 || a 

v²sledek je v₧dy logickß pravda a je jedno co je ulo₧eno v prom∞nnΘ a, nebo¥ operßtor logickΘho souΦtu pravda a cokoliv je v₧dy pravda. Je tedy zbyteΦnΘ vyhodnocovat obsah prom∞nnΘ a, proto₧e na jejφ hodnot∞ nezßle₧φ. A to je p°esn∞ to, co jazyk C d∞lß a Φemu °φkßme lenivΘ vyhodnocovßnφ.

Podobn∞ se to mß s operßtorem logickΘho souΦinu (and):

0 && a 

v²sledek je v₧dy logickß nepravda a op∞t nezßle₧φ na tom, jakou hodnotu mß prom∞nnß a.

Mo₧nß se zdß, ₧e znalost chovßnφ jazyka C je pro nßs programßtory irelevantnφ, ale nenφ tomu tak (pokud by tomu tak bylo, tak bychom o tom asi nepsali :-).

Uka₧me si n∞jak² k≤d:

// Deklarace n∞jakΘ struktury, kterß obsahuje
// jednu Φlenskou prom∞nnou. 
typedef struct 
{
  int m_x;
} SOME_STRUCT;

void main()
{
  // Definujeme prom∞nnou typu struktura
  SOME_STRUCT oStruct;
  // Definujeme prom∞nnou typu ukazatel na strukturu
  
// a zßrove≥ inicializujeme ukazatel
  SOME_STRUCT *poStruct = &oStruct;
  
  // Pokud je ukazatel inicializovßn
  if (poStruct != NULL)
    // a Φlenskß prom∞nnß je nastavena na deset
    if (poStruct->m_x == 10)
      // tak to mßme...
      printf("Je to tak!\n");
  
}

V tomto k≤du testujeme, zda je n∞jak² ukazatel na strukturu inicializovßn a pokud ano, tak otestujeme, zda jejφ Φlenskß prom∞nnß je rovna desφti. Tuto podmφnku se pokusφme zjednoduÜit:

  // Pokud je ukazatel inicializovßn
  // a Φlenskß prom∞nnß je nastavena na deset
  if (poStruct != NULL && poStruct->m_x == 10)
    // tak to mßme...
    printf("Je to tak!\n");

Zamysleme se nad tφm, co by se stalo, kdyby jazyk C poctiv∞ vyhodnocoval cel² logick² v²raz a ukazatel poStruct byl nulov². Prvnφ Φßst podmφnky je nepravdivß (z Φeho₧ plyne, ₧e cel² v²raz je nepravdiv²) a druhß Φßst podmφnky zp∙sobφ pßd aplikace. ProΦ? Proto₧e se pokusφme p°istoupit na adresu nula, kam ani nßhodou nesmφme. Jen₧e! ono to funguje, proto₧e jazyk C nenφ pitomec a kdy₧ zjistφ, ₧e prvnφ Φßst v²razu s operßtorem and je nepravdivß, dalÜφ vyhodnocovßnφ neprovßdφ. TΘto vlastnosti se vyu₧φvß velmi Φasto, proto₧e to vede k p°ehledn∞jÜφm podmφnkßm (srovnejte si ob∞ dv∞ podmφnky a doufßm, ₧e ta druhß se vßm lφbφ vφce).

DalÜφ ukßzka je spφÜe legrßcka a nidky jsem se s nφ u cΘΦkov²ch program∙ nesetkal, ale b∞₧n∞ se pou₧φvß (alespo≥ v dokumentaci) v jazyce PHP, kter² je velmi podobn² cΘΦku:

// N∞jakß funkce vracejφcφ 1 nebo 0. 
// V naÜem p°φpad∞ v₧dy nula, Φφm₧ simulujeme chybu.
int Funkce()
{
  printf("Vracim chybu...\n");
  return 0;
}

// Funkce zapouzd°uje volßnφ funkce exit()
// a je zde kv∙li tomu, ₧e bude pou₧ita v 
// logickΘm v²razu
int Konec()
{
  exit(0);  // Provede ukonΦenφ b∞hu programu
  return 0// tento return se ji₧ neprovede
}

void main()
{
  // Volßnφ Funkce, kterΘ pokud sel₧e, vyvolß funkci Konec,
  // kterß ukonΦφ program. Pokud se Funkce povede, vrßtφ
  // hodnotu logickß pravda a dφky lenivΘmu vyhodnocovßnφ se
  
// funkce Konec volat nebude a program pokraΦuje dßl.
  Funkce() || Konec();
  printf("Tak to je konec\n");  
}

D∙le₧it² je logick² v²raz, kter² je ve funkci main. Zde se nejprve volß funkce Funkce, kterß vracφ logickou pravdu p°i ·sp∞chu (1) a nepravdu (0) p°i selhßnφ. Chceme, aby po selhßnφ doÜlo k okam₧itΘmu ukonΦenφ programu, kterΘ zajistφ funkce Konec. Pokud Funkce vrßtφ hodnotu pravda, vyhodnocovßnφ se ukonΦφ, nebo¥ v²sledek je ji₧ dßn (logickß pravda) a funkce Konec se nebude volat. Pokud funkce Funkce vrßtφ nepravdu, je nutnΘ vyhodnotit i zbytek v²razu, zavolß se funkce Konec, kterß obsahuje volßnφ funkce exit, kterß okam₧it∞ ukonΦφ b∞h programu.

Bohu₧el nem∙₧eme p°φmo psßt nßsledujφcφ v²raz:

  Funkce() || exit(0);

proto₧e funkce exit nevracφ hodnotu a nelze ji tedy pou₧φt v logickΘm v²razu. Z toho d∙vodu jsme zapouzd°ili volßnφ exit do funkce Konec, kterß formßln∞ n∞jakou hodnotu vracφ. Formßln∞ proto, proto₧e k p°edßnφ nßvratovΘ hodnoty ji₧ nedojde.

Zßv∞r

Mo₧nß bychom naÜli i dalÜφ fφgle, kterΘ vyu₧φvajφ lenivΘho vyhodnocovßnφ logick²ch v²raz∙, a je tedy nutnΘ tuto vlastnost jazyka dokonale ovlßdat.


PodobnΘ Φlßnky:

Kdo Otßzka nebo p°ipomφnka

Prohlφ₧enφ p°φsp∞vk∙ nebo nov² p°φsp∞vek

O firm∞... Kontakt Ostatnφ