2009. január 24., szombat

Kétszer kettő néha öt - avagy a Warning néha Error

Találós kérdés: vajon mit ír ki az alábbi kód?

int x = 2;
int y = 2;
bool never = false;
bool ever = false;
if (x * y == 5 && never && ever);
{
    Console.WriteLine("Kétszer kettő néha öt!");
}
Persze hogy azt, hogy "Kétszer kettő néha öt!", különben nem lenne róla post, de miért?

A szemfülesek észrevehetik a feltétel sorának a végén a pontosvesszőt. Aki nem szemfüles, de legalább figyel, azt a fordító Warning: Possible mistaken empty statement üzenete figyelmezteti (egyszersmind el is magyarázza helyzetet: az if után bizony nem a feltételesnek szánt utasításblokkunk van, hanem egy árva pontosvessző, azaz egy üres utasítás).

Aki meg se nem szemfüles, se nem figyel - mint ahogy én tettem -, csodálkozhat, hogy lehet kétszer kettő öt - a Console.WriteLine() ugyanis így mindig végrehajtódik.

8 megjegyzés:

Szőke László Zsolt írta...

Szia!

Ezért nem szeretem, ill. tartom _nagyon_ rossznak ezt a stílust: azt jelzi, hogy semmi köze az előtte álló if-hez a blokknak.
Jól el kell nézni az if mögé (jobbra), hogy van-e pontosvessző, én nem szeretek jobbra nézegetni. :)

A Stroustrup ill (K&R) stílust szeretem, ott nincs ilyen probléma:

if (akármi) {
do_one;
do_two;
}
else {
do_three;
do_four;
}


A félig Struostrupot _sem_ szeretem:
if (akármi) {
do_one;
} else {
do_three;
}
Mi a bánatnak kell eldugni azt a szerencsétlen else-t?

Szőke László Zsolt írta...

Egy kicsit szar, hogy a szóközöket levágta a rendszeretek a sorok elejéről; gondoljátok oda!

Szőke László Zsolt írta...

Azt is szeretm, amikor i++ -t írkálnak ++i helyett:

for (int i = 0; i < 10; i++) {
˜˜˜do_one();
˜˜˜do_two();
}

A fordító persze van annyira okos, hogy kitalálja, hogy ez nem posztinkrement egy beépített típusnál, de lehetne i egy nem beépített típus, is.

Mindegy, eldobom azagyam, amikor amúgy képzett programozók i++-szoznak.

Na, legalább csináltam egy kis forgalmat ebben a blogban. :)

Molnár Gergő írta...

A for-os i++-os dolgot nem értem. Mi a baj vele?

Az utasításblokkok kapcsos zárójeleit jellemzően egymás alá szokták helyezni a C# világban. Könyvekben, blogokban, ajánlásokban... Ha megnézed a .NET Framework forráskódját, ott is azt látod, hogy... nos, ott azt látod, hogy ők Stroustrup stílben nyomják. De másnak nem ajánlják. :)

Akárhogy is, a programozó legnagyobb ellensége mindig saját maga lesz. Így jobb?
if (akármi); {
do_one;
do_two;
}

Ha nem figyelsz, így is, úgy is beszívod.

Szőke László Zsolt írta...

Mi az, hogy ők Stroustrupban nyomják, de másnak nem ajánlják?
Hülyeség.
Aki begépelte a doksidat, az pont Stroustup stílusban kódol, kb. ennyi.

Aki meg egy if (x); után közvetlenül begépel egy { jelet, az nyilván virágkötő, vagy tök részeg.

Vincze írta...

En sem ertem az i++ -ban mi a rossz... :)

Névtelen írta...

Sokan nem értik.

Molnár Gergő írta...

Tényleg nem értem mi a kín tárgya, pedig esküszöm, agyaltam rajta.

Érthetőségi szempontból leglogikusab magyarázatnéként arra tudtam gondolni, hogy a posztinkrement verzió sugallhatná azt, hogy az "i" régi értékének kéne részt venni a feltétel kiértékelésében, majd utána kéne megnövelni. De hát ez butaság, a for ciklus minden iterációja végén kiértékelődik a loop expression, úgy, ahogy van, legyen az akár pre-, akár posztinkrement. Utána, mint minden iteráció elején, kiértékelődik a condition (aminek nem is kell feltétlenül függnie a loop expression-től, bár nyilván a leggyakrabban az az eset fordul elő), és aztán az alapján vagy indul a következő iteráció, vagy nem.

Keresgéltem a neten is, találtam pár cikket performance témában:
http://discuss.fogcreek.com/joelonsoftware5/default.asp?cmd=show&ixPost=171881
http://dotnetperls.com/increment-preincrement-int
Na, ezek remek példái annak a totál értelmetlen mikro-optimalizációnak, amire a Zsolt típusú emberek gerjednek. Így már értem az aggódást. :) Valóban idegesítő, mikor mondjuk minden adatbázis roundtripnél elvesztünk három órajelet.

Megjegyzés küldése