Sekvenční bod - Sequence point

Sekvence bod definuje jakékoliv místo počítačového programu je provedení , při kterém je zaručeno, že všechny nežádoucí účinky budou byly provedeny z předchozích hodnocení, a přesto byly provedeny žádné vedlejší účinky následných hodnocení. Často jsou zmiňovány v odkazu na C a C ++ , protože jsou základním konceptem pro určování platnosti a, pokud jsou platné, možných výsledků výrazů. Přidání dalších sekvenčních bodů je někdy nutné k definování výrazu a zajištění jediného platného pořadí hodnocení.

V C ++ 11 bylo použití výrazu bod sekvence nahrazeno sekvenováním. Jsou tři možnosti:

  1. Hodnocení výrazu může být sekvenováno před hodnocením jiného výrazu, nebo ekvivalentně je hodnocení jiného výrazu sekvenováno po vyhodnocení prvního.
  2. Hodnocení výrazů je neurčeno sekvenováno, což znamená , že jedno je sekvenováno před druhým, ale které není specifikováno.
  3. Hodnocení výrazů je bez následků.

Provedení bezvýsledných hodnocení se může překrývat, s katastrofickým nedefinovaným chováním, pokud sdílejí stav . Tato situace může nastat při paralelních výpočtech , což způsobuje závodní podmínky . Může však již nastat v jednoduchých nesouběžných situacích, jako je například to (a = 1) + (b = a), že část přiřazení k a(např. Polovině bitů) může nastat dříve b = aa zbytek poté, takže po vyhodnocení výrazu bmůže obsahovat nesmyslný meziprodukt. stav a.

Příklady nejednoznačnosti

Zvažte dvě funkce f() a g(). V C a C ++ není +operátor spojen s bodem posloupnosti, a proto je ve výrazu f()+g() možné, že buď f()nebo g()bude provedeno jako první. Čárkový operátor zavádí sekvenční bod, a proto je v kódu f(),g()definováno pořadí vyhodnocení: nejprve f()se zavolá a pak g()se zavolá.

Sekvenční body také vstupují do hry, když je stejná proměnná upravena více než jednou v rámci jednoho výrazu. Často citovaným příkladem je výraz Ci=i++ , který zjevně přiřazuje isvou předchozí hodnotu a přírůstky i. Konečná hodnota parametru ije nejednoznačná, protože v závislosti na pořadí vyhodnocení výrazu může k přírůstku dojít před, po nebo prokládaným přiřazením. Definice konkrétního jazyka může určit jedno z možných chování nebo jednoduše říci, že chování není definováno . V C a C ++ přináší vyhodnocení takového výrazu nedefinované chování. Jiné jazyky, například C# , definují přednost operátoru přiřazení a přírůstku takovým způsobem, aby byl i=i++zaručen výsledek výrazu .

Sekvenční body v C a C ++

V C a C ++ se body sekvence vyskytují na následujících místech. (V C ++ fungují přetížené operátory jako funkce, a proto přetížené operátory zavádějí sekvenční body stejným způsobem jako volání funkcí.)

  1. Mezi hodnocením levého a pravého operandu && ( logické AND ), || ( logické NEBO ) (jako součást vyhodnocení zkratu ) a operátory čárky . Například ve výrazu jsou všechny vedlejší efekty podvýrazu dokončeny před jakýmkoli pokusem o přístup .*p++ != 0 && *q++ != 0*p++ != 0q
  2. Mezi vyhodnocením prvního operandu ternárního operátoru „otazník“ a druhého nebo třetího operandu. Například ve výrazu je za prvním bodem sekvence , což znamená, že již byl zvýšen v době, kdy je spuštěna druhá instance.a = (*p++) ? (*p++) : 0*p++
  3. Na konci plného výrazu. Do této kategorie patří expresní příkazy (například přiřazení ), zpáteční příkazy ovládající vyjádření , , , nebo - prohlášení, a všechny tři výrazy v prohlášení.a=b;ifswitchwhiledowhilefor
  4. Před zadáním funkce do volání funkce. Pořadí, ve kterém jsou argumenty vyhodnocovány, není specifikováno, ale tento sekvenční bod znamená, že všechny jejich vedlejší efekty jsou dokončeny před zadáním funkce. Ve výrazu , je volána s parametrem původní hodnoty , ale je zvýšen před vstupem do těla . Podobně, a jsou aktualizovány před vstupem a v tomto pořadí. Nicméně, to není specifikováno v jakém pořadí , , jsou prováděny, ani v jakém pořadí , , zvýšen. Pokud tělo přistupuje k proměnným a , může dojít k nárůstu obou, ani jedné nebo pouze jedné z nich. (Volání funkce je není používání napadeného čárkou, pořadí vyhodnocení pro , a není specifikována).f(i++) + g(j++) + h(k++)fiifjkghf()g()h()ijkfjkf(a,b,c)abc
  5. Po návratu funkce po zkopírování návratové hodnoty do kontextu volání. (Tento bod sekvence je specifikován pouze ve standardu C ++; v jazyce C je přítomen pouze implicitně.)
  6. Na konci inicializátoru ; například po vyhodnocení 5v prohlášení .int a = 5;
  7. Mezi každým deklarátorem v každé sekvenci deklarátoru; například mezi dvěma hodnoceními in . (Toto není příklad operátoru čárky.)a++int x = a++, y = a++
  8. Po každé konverzi spojené se specifikátorem formátu vstupu/výstupu. Například ve výrazu je bod sekvence po vyhodnocení a před tiskem .printf("foo %n %d", &a, 42)%n42

Reference

  1. ^ "ISO/IEC 14882: 2011" . Citováno 2012-07-04 .
  2. ^ "Jemněji zrnitá alternativa k sekvenčním bodům (revidovaná) (WG21/N2239 J16/07-0099)" . Citováno 2012-07-05 .
  3. ^ „Pořadí hodnocení“ . Citováno 2015-10-14 .
  4. ^ Doložka 6.5#2specifikace C99 : „Mezi předchozím a dalším bodem posloupnosti musí mít objekt uloženou hodnotu upravenou nejvýše jednou vyhodnocením výrazu. Kromě toho bude k předchozí hodnotě přístup pouze za účelem určení hodnoty pro být uloženy. "
  5. ^ Příloha Cspecifikace C99 uvádí okolnosti, za kterých lze předpokládat bod posloupnosti.
  6. ^ Standard C ++ z roku 1998 uvádí body sekvence pro daný jazyk v oddíle 1.9, odstavcích 16–18.
  7. ^ Standard C ++, ISO 14882: 2003, oddíl 1.9, poznámka pod čarou 11.
  8. ^ Standard C ++, ISO 14882: 2003, oddíl 8.3: „Každý inicializační deklarátor v deklaraci je analyzován samostatně, jako by byl v deklaraci sám.“

externí odkazy