Avatar
Homo
Člen
Avatar
Homo:
int i = 1;
int j = 5;
i += i++ + ++j + ++i + j++;

C# a Java rikaji ze i je 17.
PHP a C++ rikaji ze i je 19.

Me vyslo ze je to 17.

Tak kdo ma teda pravdu?

Odpovědět 16.6.2013 0:49
1010011 1000101 1011000
Avatar
Maxfx
Redaktor
Avatar
Odpovídá na Homo
Maxfx:

a k čemu je to dobré ?

Nahoru Odpovědět  +1 16.6.2013 4:09
Být ovládán znamená být sledován, pod dohledem, špehován, veden, uzákoněn, reglementován, ohrazen, indoktrinován, pře...
Avatar
Kit
Redaktor
Avatar
Kit:

Nikdo. Takové divočárny se nedělají :)

Nahoru Odpovědět  +1 16.6.2013 8:08
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
David Hynek
Redaktor
Avatar
David Hynek:

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)
Editováno 16.6.2013 9:19
Nahoru Odpovědět  +1 16.6.2013 9:14
Čím víc vím, tím víc věcí nevím.
Avatar
Homo
Člen
Avatar
Odpovídá na David Hynek
Homo:

Tim padem jazyky s virtualnim strojem to pekne sidi :-D

Nahoru Odpovědět 16.6.2013 9:31
1010011 1000101 1011000
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Homo
David Čápka:

A i += i++; funguje všude stejně?

Nahoru Odpovědět 16.6.2013 9:38
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Homo
Člen
Avatar
Odpovídá na David Čápka
Homo:

C++ rika 3, Java rika 2.
PHP a C# testoval Winitrix takze to ted nevim.

Nahoru Odpovědět 16.6.2013 9:45
1010011 1000101 1011000
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Homo
David Čápka:

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ě.

Nahoru Odpovědět  +1 16.6.2013 9:49
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Martin Dráb
Redaktor
Avatar
Martin Dráb:

Pravdu mají asi všichni, pokud v překladači/in­terpretu 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.

Nahoru Odpovědět 16.6.2013 11:20
2 + 2 = 5 for extremely large values of 2
Avatar
Odpovídá na Homo
Lukáš Hruda (Luckin):

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ů.

Editováno 16.6.2013 11:34
 
Nahoru Odpovědět 16.6.2013 11:33
Avatar
Homo
Člen
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Homo:

Ja to rikam furt ze MS je sra*ka :-D
Pouzivam kompilator co je ve VS2012.

Nahoru Odpovědět 16.6.2013 11:41
1010011 1000101 1011000
Avatar
Odpovídá na Homo
Lukáš Hruda (Luckin):

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.

 
Nahoru Odpovědět 16.6.2013 11:44
Avatar
Odpovídá na Homo
Lukáš Hruda (Luckin):

V Javě mi vyšlo 17, ale absolutně netuším jak k tomu ten kompilátor došel :D

 
Nahoru Odpovědět 16.6.2013 12:04
Avatar
Odpovídá na David Hynek
Lukáš Hruda (Luckin):

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.

 
Nahoru Odpovědět  +1 16.6.2013 16:21
Avatar
Luboš Běhounek (Satik):

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)

Editováno 17.6.2013 0:09
Nahoru Odpovědět 17.6.2013 0:09
:)
Avatar
Odpovídá na Luboš Běhounek (Satik)
Lukáš Hruda (Luckin):

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.

 
Nahoru Odpovědět 17.6.2013 2:13
Avatar
Odpovídá na Lukáš Hruda (Luckin)
Luboš Běhounek (Satik):

"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".

Nahoru Odpovědět 17.6.2013 8:01
:)
Avatar
Odpovídá na Luboš Běhounek (Satik)
Lukáš Hruda (Luckin):

Asi máš pravdu, ale dost bylo keců, takovouhle prasárnu stejně v životě nepoužiju... :)

 
Nahoru Odpovědět  +2 17.6.2013 11:24
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 18 zpráv z 18.