« 1 2 »
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
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
$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
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
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
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
Timy
Protože se jedná o preinkrementaci.
Timy
Profil
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
Ani ne, spíš se prostě pre-inkrementace provede před vyhodnocením výrazu,
post-inkrementace až potom
Timy
Profil
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
Timy:
Preinkrementace se provede před samotným sčítáním, takže musí mít vyšší prioritu.
…a skutečně jí také :)
Timy
Profil
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
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
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
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
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
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
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
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
Já taky ne.
Timy
Profil
tak už nic
Mastodont
Profil
Jo, už jsem si toho všimnul :-)
tiso
Profil
Timy - http://sk.php.net/manual/en/language.operators.precedence.php
Timy
Profil
tiso
Nechápu.
TomášK
Profil
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
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
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
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
[#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
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ě?
« 1 2 »

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0