Autor | Zpráva | ||
---|---|---|---|
igamenir Profil |
takový divný vzoreček, na který jsem narazil:
$i = 1; echo $i+(++$i); dle mého soudu se v má spočíst 1 + 2, takže 3. Výsledek je ale 4 - proč? mimochodem $i+++$i skutečně vrátí 3; |
||
Nox Profil |
#2 · Zasláno: 12. 3. 2009, 11:44:42
Můj názor:
i = 1 první se vyhodnotí závorka => i=2 => echo 2+2 Minimálně v C ale nejsou tyto konstrukce ani definované a nedoporučují se používat, není to ani nijak čitelné, takže ikdyž by se možná daly dohledat nějaká pravidla (PHP už by to definované mít mohlo), tak je otázka, zda to takto opravdu chceš používat. Úspora kódu je zanedbatelná |
||
AM_ Profil |
#3 · Zasláno: 12. 3. 2009, 15:02:39
$i+++$i je imho vzhledem k prioritě unárních operátů pochopeno jako ($i++)+i. Zajímavé, od toho bych spíš čekal, že to vrátí 4, ale to je přesně důvod, proč takovéhle čuňačiny nepoužívat.
|
||
Nox Profil |
#4 · Zasláno: 12. 3. 2009, 15:11:17
AM_
Ale $i++ je přece až post inkrementace, takže tak neočekávané to není... ($i++)+$i=(1)+1 a po provedení +1 => 3 Nebo aspoň tak to chápu....ale stejně je to asi jedno, v tom, že to není přínosné používat sme se shodli |
||
Mastodont Profil |
#5 · Zasláno: 12. 3. 2009, 15:21:56 · Upravil/a: Mastodont
igamenir
Je to 4, protože se $i nejdřív zvětší o jedničku, poté se teprve začne vyhodnocovat to sčítání, a tam už se sčítají dvě dvojky. $i+(++$i) // teď je $i = 1 // $i se inkrementuje o 1 $i+$i // teď je $i = 2 |
||
Timy Profil |
#6 · Zasláno: 12. 3. 2009, 15:47:07
Mastodont
Z jakého důvodu se nejdřív vyhodnotí ++$i? Zkusil jsem si v C (kde se to chová stejně) napsat tento kód a normálně se mi na obrazovku vypíše „první druhá“, tedy první argument u sčítání se vyhodnotil dříve než druhý. Docela by mě zajímalo, v čem je zakopaný pes, takový C# nebo Javascript mi vrací normálně trojku. |
||
Mastodont Profil |
#7 · Zasláno: 12. 3. 2009, 16:08:07
Timy
Protože se jedná o preinkrementaci. |
||
Timy Profil |
#8 · Zasláno: 12. 3. 2009, 16:13:05
Mastodont
No tos mi toho řekl… Není to spíš tak, že ona preinkrementace má v C/PHP vyšší prioritu než sčítání? |
||
Nox Profil |
#9 · Zasláno: 12. 3. 2009, 16:17:37
Ani ne, spíš se prostě pre-inkrementace provede před vyhodnocením výrazu,
post-inkrementace až potom |
||
Timy Profil |
#10 · Zasláno: 12. 3. 2009, 16:22:01
Nox
„spíš se prostě pre-inkrementace provede před vyhodnocením výrazu“ Jakého výrazu? Preinkrementace se provede před samotným sčítáním, takže musí mít vyšší prioritu. Pokud by s tím priorita neměla co dělat, vyhodnotilo by se to tak, že by se začalo sčítat. $i by se vyhodnotilo na jedničku a pak by se teprve $i zvedlo na 2 a přičetla by se ta dvojka a výsledek by byl 3. Protože má ale ++$i vyšší prioritu než sčítání, nejprve se vyhodnotí ++$i, takže $i má hodnotu 2 a až pak se začne sčítat 2 + 2 = 4. |
||
Jan Tvrdík Profil |
#11 · Zasláno: 12. 3. 2009, 16:30:42
Timy:
„Preinkrementace se provede před samotným sčítáním, takže musí mít vyšší prioritu.“ …a skutečně jí také má :) |
||
Timy Profil |
#12 · Zasláno: 12. 3. 2009, 16:32:46
Jan Tvrdík
Já (už) vím :-). C# nemá, má vyšší prioritu u sčítání, proto se tam ty výrazy vyhodnotí lidsky. |
||
Mastodont Profil |
#13 · Zasláno: 12. 3. 2009, 16:41:30
Timy
C# nemá, má vyšší prioritu u sčítání Vážně? Takže následující stránka kecá? http://msdn.microsoft.com/en-us/library/aa691323(VS.71).aspx No tos mi toho řekl Buď rád, že jsem vůbec něco řekl :-) Základy by si měl každý nastudovat sám :) |
||
Nox Profil |
#14 · Zasláno: 12. 3. 2009, 17:14:47
Timy
Celého výrazu (tzn. třeba strlen("abcd")*$a++*$b+3 )...podle mě není vůbec třeba prioritu řešit, především kvůli $i++, protože kdyby se tomu pouze dala nejnižší priorita, tak stejně se to provede už v tom samém výrazu, ve kterém je to napsané, což je špatně. Pokud by bylo spešl řešené $i++, tak proč mít každé řešené jiným způsobem...prostě ++$i a $i++ se vyhodnotí mimo vlastní výraz. => toto jsem nikde výslovně neřekl, přesto mi to připadne jako nejlogičtější možnost. |
||
Timy Profil |
#15 · Zasláno: 12. 3. 2009, 18:40:10
Mastodont
„Vážně? Takže následující stránka kecá? “ The following table summarizes all operators in order of precedence from highest to lowest: + - ! ~ ++x --x (T)x Já tam tedy vidím + před ++x. Tento identický kód… int i = 1; Console.WriteLine("Výsledek: {0}.", i+(++i)); …vypíše v C# „Výsledek: 3.“ Jak je to možné, pokud by měl mít C# u operátoru ++x vyšší prioritu než u +? Nox „Celého výrazu“ To nemá moc logiku a ani to tak nefunguje. $i = 1; echo $i+$i+(++$i); // Nevypíše 6 function pokus($cislo) { echo "|", $cislo, "|"; return 0; } $i = 1; echo pokus($i)+(++$i); // Nevypíše |2|2 …jestli jsem tě tedy dobře pochopil :-). |
||
Mastodont Profil |
#16 · Zasláno: 12. 3. 2009, 19:00:00
Timy
To je divné, zkus to bez těch závorek: Console.WriteLine("Výsledek: {0}.", i + ++i); Já tam tedy vidím + před ++x. To ano, ale všimnul sis, co je napsáno na začátku toho řádku? "Unary" A to není sčítání. Sčítání máš o dva řádky níže. |
||
TomášK Profil |
#17 · Zasláno: 12. 3. 2009, 19:43:22 · Upravil/a: TomášK
Timy
Nerozlišuješ unární (+3) a binární (3+3) operaci, proto vidíš + před ++ ;-) IMHO se řešení nejde dobrat jen pomocí prority - priorita jen říká, jak se to uzávorkuje. Uvažuju-li výraz i+(++i) pak je to (opět domněnka) ekvivalentní volání funkce operator_plus(i,(++i)) a pořadí vyhodnocení argumentů funkce není definované, může to dopadnou jakkoliv (=zformátuje to disk hned poté, co odešle šéfovi mail s výpovědí). Proto to v každém jazyce může dávat něco jiného (předpokládám, že to není definované v žádném, ale podložené to nemám). |
||
Timy Profil |
#18 · Zasláno: 12. 3. 2009, 19:55:48
Mastodont
No jo, toho jsem si nevšiml. Tak pak to je divné :-)). i + ++i vrátí totéž, tři. Mimochodem $i+$i+(++$i) vrátí totéž jako $i+(++$i) :-) TomášK „a pořadí vyhodnocení argumentů funkce není definované“ Já bych řekl, že definované je a v podstatě to lze snadno vyzkoušet: http://www.clipboard.cz/6vj Vypíše „první druhá“. |
||
Timy Profil |
#19 · Zasláno: 12. 3. 2009, 22:32:02 · Upravil/a: Timy
Pořád mám pocit, že jsme se nedobrali řešení. Takže ví někdo, jak to skutečně je? Tedy proč to v PHP/C++ vrací čtyřku, ale v C# nebo třeba i v Javascriptu trojku? Priorita operátorů je tedy všude stejná a v C asi dává největší smysl:
i=1; i + ++i --> ++i má větší prioritu než sčítání, takže se provede a je z toho čtyřka. i + i + ++i --> odpovídá to uzávorkování ((i + i) + ++i), takže se sečte 1 + 1 a až pak se provede inkrementace a výsledek je zase 4. Pokud změním závorky: (i + (i + ++i)) --> opět se nejprve provede ++i a pak se sečtou tři dvojky, výsledek 6. Situace v C#/JS: var i = 1; alert(i + ++i); --> evidentně se nejprve vypočte „i“ a pak už se počítá 1 + ++i = 3 alert(i + i + ++i); --> výpočet probíhá stejně jako v C: výsledek je 4. alert(i + (i + ++i)); --> žádná změna, výsledek 4. ==> Takhle to teda zatím chápu já. Jaký je mezi těmi jazyky rozdíl? Pořadí vyhodnocení argumentů by mělo být všude stejné — co si pamatuji ze školy, tak C naháže argumenty na zásobník zprava doleva, takže na vrcholu zásobníku je první argument. C# a JS se IMHO chová stejně (tuším, že přednášející zmiňoval, že Pascal se chová obráceně), navíc kdyby vyhodnocoval operandy opačně, „i + ++i“ by se nemohlo rovnat třem. Takže kde je zakopaný pes? Já tomu pořád nerozumím :-). |
||
Mastodont Profil |
#20 · Zasláno: 12. 3. 2009, 22:44:36 · Upravil/a: Mastodont
Já taky ne.
|
||
Timy Profil |
#21 · Zasláno: 12. 3. 2009, 22:47:13 · Upravil/a: Timy
tak už nic
|
||
Mastodont Profil |
#22 · Zasláno: 12. 3. 2009, 22:48:07
Jo, už jsem si toho všimnul :-)
|
||
tiso Profil |
#23 · Zasláno: 12. 3. 2009, 22:51:45
|
||
Timy Profil |
#24 · Zasláno: 12. 3. 2009, 22:53:35
tiso
Nechápu. |
||
TomášK Profil |
#25 · Zasláno: 12. 3. 2009, 23:04:57
Timy
Já bych řekl, že definované je a v podstatě to lze snadno vyzkoušet: http://www.clipboard.cz/6vj Vypíše „první druhá“. Nerozumíme si. Pod pojmem není definovené myslím to, že ve normě jazyka C není uvedeno, v jakém pořadá se to musí vyhodnotit. Tedy každý překladač to může dělat jinak, podle toho, jak zrovna on uzná za vhodné. Udělá to typicky buď jedním nebo druhým způsobem, takže to projde a kód proběhne, ale ty nevíš dopředu, jak - když to přeložíš něčím jiným, může se to chovat jinak. A protože jiné jazyky mají jiné překladače, tak to dělají podle svého a to pořadí si vyberou tím druhým způsobem, protože jim norma neříká, jak to mají udělat. |
||
Timy Profil |
#26 · Zasláno: 12. 3. 2009, 23:07:13
TomášK
Aha. No hádat se nebudu, normu C neznám. Nás učili, že C si to naháže na zásobník zprava doleva, vyhodnocení pak probíhá logicky opačně. Jestli to ale není v normě a různé překladače to dělají různě, nevím. C není můj oblíbený jazyk :-). |
||
TomášK Profil |
#27 · Zasláno: 12. 3. 2009, 23:23:29 · Upravil/a: TomášK
Já taky nejsem natolik zběhlý, abych za to, co říkám strčil ruku do ohně. Ale myslím, že to nejsou úplné nesmysly:)
Na zásobníku to je určitě v pevném pořadí (mám pocit, že se to řídí podle pc, ale dost matný :) ), ale tam se ukládají až vyhodnocené objekty. Někdy předtím se musí vyhodnotit, a tam podle mě nevíš, jak to proběhne. Má to i rozumný smysl - motivace, proč to není pevně dané, je taková, aby se to případně mohlo vyhodnotit paralelně. V takovém případě by se side-efekty byl problém. Myslím si, že ostatní jazyky to budou mít stejně jako C - nedefinované. Čímž by šlo vysvětlit, proč to každý dělá jinak :) Edit: Z normy C99 EXAMPLE In the function call 12 (*pf[f1()]) (f2(), f3() + f4()) the functions f1, f2, f3, and f4 may be called in any order. All side effects have to be completed before the function pointed to by pf[f1()] is called. |
||
Timy Profil |
#28 · Zasláno: 12. 3. 2009, 23:41:18
TomášK
„mám pocit, že se to řídí podle pc, ale dost matný :)“ Kapitola 3.2 na straně 27, část Předávání parametrů — Konvence C. Ale je pravda, že se tam nemluví o tom, kdy se to vyhodnotí, jen jak se to pak naháže na zásobník, a to je nám už vlastně na prd. „Čímž by šlo vysvětlit, proč to každý dělá jinak :)“ Ale když nepoužiji jen ++ operátory, ale i funkce, které mají vedlejší efekt (výpis na obrazovku), tak je vidět, že to všechny zmíněné jazyky a překladače vyhodnocují zleva doprava. Ona už vlastně není záhada u C++, tam se to chová logicky vzhledem k tomu, že ++i má vyšší prioritu než +, záhada je, proč se C#/JS chová tak jak se chová. Tedy — pokud má operátor ++i vyšší prioritu než + (což ve zmíněných jazycích má), měl by se výraz „i + ++i“ vyhodnotit na 4: proč JS/C# vrací trojku? |
||
tiso Profil |
#29 · Zasláno: 13. 3. 2009, 00:29:19
[#24] - to je tabuľka priority operátorov spolu so smerom ich vyhodnocovania v PHP. Ostatné jazyky by mali mať niečo podobné. Hlavný dôvod prečo som to sem uviedol je ten, že sú operátory, ktoré sa vyhodnocujú v opačnom poradí.
|
||
TomášK Profil |
#30 · Zasláno: 13. 3. 2009, 00:55:40
Timy
Dík za link, už mi svitlo, že ono to jinak než jedním způsobem nemůže jít. A i vím kde jsem vzal svou vzpomínku o více způsobech - v literatuře někdy zásobník roste nahoru, někdy dolů, někdy doprava - a odtud se mi zafixovalo, že je víc možností, jak to jde. Priorita mi říká, že výraz ++i + i se uzávorkuje jako (++i) + i ne jako ++(i+i). Výraz i + ++i se uzávorkuje (i + (++i)). Neříká mi, jak se to vyhodnotí. Zkoušel jsem následující: #include <stdio.h> int fce1() { printf("prvni\n"); return 1; } int fce2() { printf("druha\n"); return 1; } void sum(int a, int b) { printf("Cislo z funkce: %d\n", a+b); } int main(int argc, char *argv[]) { printf("Cislo ze souctu: %d\n", fce1() + fce2()); sum(fce1(), fce2()); return 0; } Výstup: prvni druha Cislo ze souctu: 2 druha prvni Cislo z funkce: 2 Je z toho vidět, že se funkce nechová stejně jako sčítání. Můžeš zkusit, jestli to u tebe dopadne stejně? |
||
Téma pokračuje na další straně.
|
0