8 maja 2009

Niebezpieczne makra cz II.

Spójrzmy raz jeszcze raz na program. Po podstawieniu za makro instrukcji if jest on postaci:
// Program pierwszy
if (warunek1)
if (warunek2)
instrukcja1;
else
instrukcja2;
Spostrzegawczy czytelnik na pewno zauważy, że instrukcja2 tak na prawdę powinna być kolejnym ifem, jednak dla czytelności kodu zostawię ją tak jak jest.
W programie nie ma nawiasów klamrowych. Wcięcia sugerują, że instrukcja2 powinna zostać wykonana wtedy, gdy nie spełniony zostanie warunek1. Jednakże kompilator nie zwraca uwagi na wcięcia. Powyższy program i poniższy są dla kompilatora identyczne:
// Program drugi
if (warunek1)
if (warunek2)
instrukcja1;
else
instrukcja2;
Widzimy, że te dwa programy różnią się od siebie. Instrukcja2 wykonywana jest tylko wtedy gdy zostanie spełniony warunek pierwszy i niezostanie spełniony warunek drugi.
Powyższe programy dla kompilatora który ignoruje białe znaki jest identyczny? Pytanie zatem: jak kompilator traktuje taki kod. Tak jak program pierwszy czy tak jak program drugi? Okazuje się że gdy kompilator napotyka słowo kluczowe "else" próbuje je związać z ostatnią napotkaną pętlą "if". Zatem zinterpretuje kod źródłowy tak jak w programie drugim.

Aby unikać takich sytuacji dobrze jest stosować nawiasy klamrowe w ifach. Dobrym pomysłem jest też zamykanie w klamry całego makra.

Brak komentarzy: