> pro vyhodnocování výrazů a funkcí v nich platí ve Fortranu
> poněkud jiná pravidla než v C (a jeho potomcích). V C mohou
> funkce ve výrazech dělat cokoliv, protože lze přesně určit
> pořadí, v jakém se budou vyhodnocovat.
--- to není pravda, fixní pořadí vyhodnocování platí jen pro pár operátorů v C (&& || ?: ,), pro ostatní operátory je pořadí vyhodnocení nedefinované.
BTW. Platí v C to, že funkce se ve výrazu musí zavolat, i když na ní nezáleží? --- t.j. např. ve výrazu 0*f(), musí kompilátor zavolat tu funkci f()? Já myslím, že musí, ale nejsem si tím teď jist. (v případě && || ?: je specifikováno, že se to část, na které nezáleží, vyhodnotit nesmí, jak je to u ostatních operátorů --- musí se vyhodnocovat nebo mohou?)
Fixní pořadí vyhodnocování měl myslím Pascal (a kompilátory to z důvodu optimalizace umožňovaly vypnout).
>> BTW. Platí v C to, že funkce se ve výrazu musí zavolat, i když na ní nezáleží? --- t.j. např. ve výrazu 0*f(), musí kompilátor zavolat tu funkci f()? Já myslím, že musí, ale nejsem si tím teď jist.
Ja bych rekl, ze u aritmetickych operaci se zavoalt funkce musi. Jeji vysledek muze byt treba NaN (Not a number, trepa po deleni nulou), a pak je cely vysledek spatne.
Jasně, mea culpa, tady jsem to trochu přehnal.
Podle C99 jsou sequence points jenom v logických operátorech, čárce a ternárním operátoru.
Zdá se mi to, nebo jich v C89 bylo víc? Ten teď nemám po ruce, takže to nemůžu ověřit.
Pokud jde o váš druhý dotaz, tak nemusí, pokud funkce nemá boční efekt. V C99 je to výslovně
zmíněno (někde na začátku). U knihovních funkcí to tedy zřejmě bude vědět, u uživatelských asi podle složitosti a stupně optimalizace. I kdyby to tam zmíněno nebylo, tak je to logické, protože když funkce nemá boční efekt, tak se vlastně nic nepozná. Tedy to pokud f() je int, float může mít něco jako NaN a Inf, které násobením nulou nedají nulu.
Překladač Fortranu má tedy tu výhodu, že to nemusí řešit (čili nemusí ji vyhodnotit, ani když má boční efekt). Fortran tak požaduje od programátora větší disciplínu. IMHO ale boční efekty
ve výrazech jsou celkem zavrženíhodné.
Odkaz, který jsem sem poslal, říká: "Their associativity indicates in what order operators of equal precedence in an expression are applied." Je fakt, že není možné aplikovat operátor na operandy, které nejsou dosud vyhodnocené, ale na druhou stranu samozřejmě není nutné, aby tyto operandy byly vyhodnocené v nějakém pevném pořadí. Spoléhat se na to nedá, to je pravda, takže jsem asi trochu mystifikoval (ikdyž bych si tipnul, že normální člověk by to pořadí asi dělal stejně podle té asociativity). Ale zase, pokud někdo spoléhá na toto pořadí a jeho funkce, jejichž návratová hodnota se používá v aritmetických operacích, mají tak brutální boční efekty, je to prase a dobře mu tak, když se spálí.
IMHO tu funkci volat nemusi, protoze muze v ramci optimalizaci provest jeji "inlining" a potom treba zjisti, ze se jedna o konstantni vyraz. Nebo se ta funkce vola uvnitr smycky se stejnymi parametry (a nema vedlejsi efekt) - pri optimalizaci se ta funkce predpocita. Taky mam dojem, ze prekladac muze i podle normy vyhodit i cele bloky kodu, u kterych je zrejme, ze se stejne neprovedou (dead code elimination?).
U funkci, ktere maji vedlejsi efekty je to samozrejme jinak a u logickych vyrazu s && a || je zkracene vyhodnoceni primo predepsano (nekdy by se hodilo toto "vypnout" nebo mit dve sady operatoru ala Java, protoze treba v makrech to dela problemy).
Domnivam se, ze i vyse uvedeny priklad po optimalizaci nemusi provest volani f(). Vzhledem k tomu, ze k zasadam cisteho programovani ma patrit i to, ze volani takove funkce nema mit vedlejsi ucinky na celkovy kod (a nedej boze na obsah stavovych promennych apod.) by to u vsech rozumne myslitelych bytosti (ktere si chteji zachovat dusevni silu) nemelo vadit...:-)
Obecne bych problem spise videl v tom, jak automatizovane poznat, ktera vypustka vadi a ktera ne... - bud proste optimalizujeme konstrukce tohoto razu (kdekoli) nebo ne.
PS: A uz bych se vubec do techto uvah nepoustel z titulu chybovosti prekladacu. To, ze to 100x na exemplarnim prikladu zkusim a prelozim a ono to konstrukci prelozi dle ocekavani vubec neznamena, ze pri 101. prekladu to cele nedopadne jinak. Ostatne, kernelovi programatori by mohli vypravet... (a zdaleka nejen oni)
f(): Musí se vyhodnotit, pokud kompilator nezjisti, ze se to nepozna. gcc ma k tomu __attribute__((pure)) a __attribute__((const)) [a samozrejme se to da videt z (inlinovanyho) kodu]
Celkem nedavno jsem videl nejaky standard Pascalu, kde bylo poradi vyhodnocovani parametru funkci nespecifikovane. Jak je to s vyrazy nevim.
MMCH jak je to presne v C se sequence pointy? Standard C neznam, mam jen C++ a dejme tomu
a++; b++;
je v C++ mozno vyhodnotit v jakemkoli poradi, pokud obe vedou ke stejnemu vysledku (a a, b nejsou volatile a nejde o volani funkce).