O wyższości kompilatora nad preprocesorem

C++ od początku odziedziczył wiele elementów swojego poprzednika – języka C. Preprocesor wraz z dyrektywami są jednym z takich elementów. O ile we wcześniejszych wersjach C++ często używano preprocesora, tyle w nowych standardach (szczególnie od C++98/03) zaczęło się to zmieniać. Język zaczął intensywnie zmieniać swoje oblicze i preprocesor zeszedł na dalszy nieco plan. Tym niemniej u starszych programistów spotyka się nawyk nadużywania preprocesora, zapewne jako pozostałość dawnych czasów. Obecnie preprocesora dobrze używać tylko tam, gdzie to jest naprawdę konieczne. Niedawno w projekcie, który utrzymuję spotkałem błąd, który był trudny do zdiagnozowania. Otóż podczas przebudowywania projektu kompilator zaczął zgłaszać brak definicji wartości 2,7182… oraz 1,6108… Jest to oczywiście liczba Eulera oraz liczba fi. Obie są przedmiotem nauczania na pierwszym roku studiów informatycznych, zatem programista nie powinien mieć problemu z ich rozpoznaniem. Trudniej jednak rozpoznać co się stało, że zniknęły. Skoro wcześniej wszystko działało jak należy powinny być zdefiniowane w niniejszej aplikacji. Po dochodzeniu okazało się, że owe „magiczne” liczby zostały zdefiniowane w preprocesorze w klasyczny sposób:

#define EULER 2,718281828459
#define FI 1,6180339887

Coś po drodze je jednak „zjadło”. Tym czymś był oczywiście sam preprocesor, który je usunął zanim wszystko zdążył skonsumować kompilator. Zatem w tablicy symboli kompilator nie mógł ich odszukać i generował błąd. Rozwiązanie? Jest bardzo proste. Należy używać defenicji stałych dla kompilatora w postaci:

const double euler = 2,718281828459;
const double fi = 1,6180339887;

Takie dane są zawsze zawarte w tablicy symboli i komplator jest szczęśliwy.
Wtedy gra muzyka i aplikacje śmigają jak należy. Po rpostu tam, gdzie to jest możliwe należy unikać preprocesora na korzyść kompilatora. To samo dotyczy definiowania funkcji, bo czasem czytanie źle napisanego kodu aż boli jak tu:

#define FIRST_VALUE_MAX(x,y) f((x)>(y)?(y):(x))

Funkcje podobnie jak i stałe lepiej definiować poza preprocesorem. Wtedy unikniemy wielu problemów.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *