C kviz

Jan Waclawek konfera na efton.sk
Úterý Prosinec 6 14:43:05 CET 2016


>Formalne moze byt vysledok nedefinovany, bo v jednom prikaze sa meni
>hodnota premennej a dvakrat.

No toto je to (nie ze vysledok je nedefinovany, ale spravanie je
nedefinovane).

C99, 6.2#2:
Between the previous and next sequence point an object shall have its
stored value
modified at most once by the evaluation of an expression.


>Ale prakticky to je v tomto pripade jedno, do a sa priradi spravna
>hodnota (7), nezavisle od toho, kedy sa a inkrementuje - hodnota a ma
>lavej strane priradenia nema na nic vplyv. 

Je pravda, ze ta hodnota na nic nema vplyv (ak za tym nenasleduje kod ktory
ju pouziva - znova je to to moje ledabole zadanie), ale nemusi sa do neho
priradit spravna hodnota - su tam dve priradenia a tak vysledkom je
nedefinovane spravanie (kvoli slovicku "shall"), t.j. moze to fungovat tak
ako bolo zamyslane, moze to fungovat uplne inak (napr. sa moze priradit do
neho vysledok toho inkrementu, alebo aj cokolvek ine), moze to dokonca
sposobit pad programu, chybu pri preklade, pad prekladaca, pad OS, alebo
koniec sveta ako ho pozname, proste cokolvek. To, ze gcc, alebo hoci aj
vsetky zname prekladace to bez problemov prelozia do bez problemov
fungujuceho kodu, je irelevantne.

Ale bez srandy, dovodom je definicia tych "sequence points". To su body, v
ktorych musi prekladac zabezpecit ze vsetky volatile a ekvivalentne
pristupy ktore doteraz v kode boli, su uz vykonane, a tie, ktore v kode
nasleduju, neboli zacate. Medzi nimi si moze robit, co len chce; je
povinnostou programatora dodrziavat pravidla. Tymto je vlastne definovana
volnost, ktoru ma prekladac v optimalizaciach. Kvoli optimalizaciam je
vhodne, aby tie sequence points boli co najzriedkavejsie. Hrubo povedane,
sequence point je v mieste kde je za vyrazom bodkociarka, dalej pred
volanim funkcie po vyhodnoteni vyrazov ktore urcuju hodnoty parametrov, a
okrem toho je este par takych nie uplne beznych bodov s pomerne zlozitym
odovodnenim (zoznam sequence points je v C99 Annex C). Treba si pritom
uvedomit, ze priradenie v C je operator, ktory ma tiez vysledok, a tym
predstavuje sucast vyrazu. Toto, spolu s faktom, ze existuje aj iny
operator nez priradenie, ktory meni hodnotu premennej (menovite ++ a -- v
oboch formach), je zasadny rozdiel oproti "algoloidnym" jazykom, ktore su
v tomto ohlade "bezpecnejsie".

Poziadavka jedineho zapisu do jednej premennej je pomerne pochopitelna.
Dovoluje to prekladacu/vykonavaciemu stroju medzi dvomi sequence points
pouzit bez rozmyslania lubovolne poradie ukladania vysledkov (ak je viac
premennych) - proste ak sa zapisovalo do roznych premennych tak je to OK,
ak do roznych tak to je programatorov problem.

gcc na tento problem upozornuje warningom typu -Wsequence-point.

Mimochodom, footnote 72 k citovanej polozke z C99 znie:

This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;


>Ten radek a=++a%10; podle vas neni (nemel by byt) ekvivalentni radkum
>++a;
>a %= 10;

No praveze nie je, pretoze tu je sequence point uz za tym prvym vyrazom.

wek



Další informace o konferenci Hw-list