Diskuze: Stejny priklad ruzne vysledky
Člen
Zobrazeno 18 zpráv z 18.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
Správně je 19.
i = 1
j = 5
i += i++ + ++j + ++i + j++
tedy
I sečtení pro (x++) i += 2 + 5 + 1 + 6 = 14 (i++ a j++ se provedly před výpočtem)
II sečtení pro (++x) i += 14 + 2 = 16 (++i a ++j se provedly po výpočtu)
III sečtení pro (i +=) i = 16 + 3 = 19 (a samo i se z 1 se přičtením i++ a ++i změnilo na 3)
C++ rika 3, Java rika 2.
PHP a C# testoval Winitrix takze to ted nevim.
No tak v tom je ten problém Ono záleží jak si to vyložíš. Má se změna proměnné vpravo projevit v hodnotě vlevo? Ani jeden výsledek není špatně.
Pravdu mají asi všichni, pokud v překladači/interpretu některého z testovaných jazyků není chyba. Aby se tohle dalo více řešit, bylo by třeba přečíst normy všech těch jazyků, jinak to podle mě nemá smysl.
Mě vyšlo 18 a 2 kompilátory na C a na C++ mi to potvrdily, tvůj kompilátor C++ pravděpodobně nedodržuje standard, Java a C# mají očividně jiné priority operátorů.
Ja to rikam furt ze MS je sra*ka
Pouzivam kompilator co je ve VS2012.
VS má dobré vývojové prostředí, ale nepřekvapuje mě, že nedodržuje standardy, sám jsem se o tom přesvědčil kdysi ve VS 2010 (už nevím co to bylo, ale také v něčem nedodržovalo standard). Nejlépe je na tom s dodržováním standardů údajně gcc, čemuž i věřím.
V Javě mi vyšlo 17, ale absolutně netuším jak k tomu ten kompilátor došel
Tuším, že to máš obráceně. i++ a j++ se provádí po výpočtu (po výpočtu pravé strany, operátor += má nejmenší prioritu z vyskytujících se operátorů), ++i a ++j se provádí před výpočtem (nebo spíše přímo při výpočtu). Celkový výsledek očividně závisí na jazyce, ale mám pocit, že všechny C-like jazyky by teoreticky měli dodržovat priority operátorů jazyka C, pak je správný výsledek 18.
C++ na tohle ani standard nemá (má jen standard samotný postfix/prefix ++
a --).
Čekal bych, že ostatní jazyky asi také tohle ve standardu neřeší.
Takže dokonce i různé C++ kompilátory můžou produkovat různý výsledek a
není to chyba, prostě to jen implementují jinak.
int i = 1;
int j = 5;
i += i++ + ++j + ++i + j++;
U MSVS kompilátorů výpočet probíha následovně, ++ přičítá hned za
(resp. před) každým členem výpočtu:
i += 1 (i=2) + (j=6) 6 + (i=3) 3 + 6 (j=7)
z čehož nám vyjde
i += 16
Rozdíl teď může být v tom, jestli se za to počáteční i dosadí hodnota i před výpočtem (1+16, výsledek 17) nebo hodnota i po výpočtu (3+16, výsledek 19).
MSVS C++ mi vrací 19 a MSVS C# 17 (pro jistotu jsem to ozávorkoval, abych vyloučil různé priority operátorů).
Luckinův kompilátor to počítá ještě jinak, odhaduji, že jeho kompilátor bere jako výraz celý řádek a ne jednotlivé prvky, takže se ten kód
i += i++ + ++j + ++i + j++;
přeloží zhruba na tohle:
++i;
++j;
i += i + j + i + j;
i++;
j++;
z čehož nám vyjde, když do výpočtu dosadíme aktuální hodnoty:
i += 2 + 6 + 2 + 6
tedy
i += 16
(v tu chvíli je i 2, tedy výsledek je 2+16 = 18)
Ne tak docela.
Kompilátor nejdříve spočítá pravou stranu tedy:
i++ + ++j + ++i + j++
Kompilátor postupuje zleva doprava, tudíž vezme nejdříve i jako 1, pak j ke
kterému rovnou přičte 1 tedy bere ho jako 6 a j je zvýšeno na 6, pak i ke
kterému rovnou přičte 1 tedy bere ho jako 2 a i je zvýšeno na 2, následuje
j které je bráno jako 6.
Na levé straně tedy dojde k výrazu:
1+6+2+6 = 15
Následně se spočítají výrazy j++ a i++, tedy i je zvýšeno na 3 a j na
7.
i += 15 tedy přiřadí do i hodnotu 3 + 15 tedy 18.
Standard C++ říká, že prefix (++i/++j), má vracet hodnotu prvku již
zvýšeného a postfix (i++/j++) hodnotu prvku před zvýšením.
i++ + ++j + ++i + j++ by totiž kompilátor měl brát jako jeden výraz a
postfixy spočítat až nakonec. VS přičte k i jedničku hned po prvním +
tedy hned po vykonání i++ + ++j, bere to jako volání funkcí:
i++.operator+(++j.operator+(++i.operator+(j++)))
Je pravda, že na tohle standard asi není. Pak tedy i výsledek 19 je
teoreticky správně.
Ovšem to, že kompilátor při přiřazení postupuje zprava doleva a že
operátor += má menší prioritu než + a ++ by standardem dáno být mělo.
Tedy nejdříve se provede výraz na pravé straně a pak samotné přiřazení,
na levé straně tedy podle mě musí vždy být hodnota 3.
"Ovšem to, že kompilátor při přiřazení postupuje zprava doleva a že
operátor += má menší prioritu než + a ++ by standardem dáno být
mělo."
Však tak je to i v C++ i v C# i od MS, na tomhle se nic nemění, to je všude
stejné.
Ono jde o to, že pod
i += i++ + ++j + ++i + j++;
si třeba já (a C#) představím to samé, jako je
i = i + (i++ + ++j + ++i + j++);
tedy že jako to i, ke kterému se přičítá, se bere ta počátační hodnota i .
V normě právě není specifikováno, jestli se za ten výraz má považovat samotné i++ nebo celý "řádek".
Asi máš pravdu, ale dost bylo keců, takovouhle prasárnu stejně v životě nepoužiju...
Zobrazeno 18 zpráv z 18.