2014-04-23 13 views
7

Czytam kod źródłowy. I to nie tylko kod źródłowy, ale również wiele innych, korzystać z tego rodzaju programowania:Po co używać zdefiniować słowo kluczowe do definiowania funkcji

#define DO_BINOP(FN_NAME,TFLAG,OPER) \ 
    void FN_NAME (bigint_stack &stack) { \ 
     bigint right = stack.front(); \ 
     stack.pop_front(); \ 
     TRACE (TFLAG, "right = " << right); \ 
     bigint left = stack.front(); \ 
     stack.pop_front(); \ 
     TRACE (TFLAG, "left = " << left); \ 
     bigint result = left OPER (right); \ 
     TRACE (TFLAG, "result = " << result); \ 
     stack.push_front (result); \ 
    } 

DO_BINOP(do_add, '+', + ) 

Używają define zdefiniować długo długi łańcuch, który działa jako funkcja. Nie wiem, jaką korzyść z tego wynika, ponieważ w ten sposób program jest trudniejszy w czytaniu i trudniejszy w debugowaniu. Jestem nowy w C, więc myślę, że ta metoda musi przynieść jakieś korzyści, prawda?

Dzięki.

+5

W ten sposób można zdefiniować wiele funkcji różniących się tylko nazwą i operacją, używając tylko jednego wywołania makra dla każdej instancji. –

+0

Ponieważ ta osoba jest sadystyczna. Poważnie, jest to sposób na wymuszenie in-lining. To może być trochę więcej ... standardowe złamanie. W tym przypadku jest tak dlatego, że osoba, która jest górą, przekazuje argument operatora jako operatora. – IdeaHat

+4

@MadScienceDreams Makro * definiuje * funkcję po wywołaniu (zamiast rozszerzania do wyrażenia, jako funkcji złego człowieka), tak więc w tym przypadku nie ma powodu związanego z inliningiem. – delnan

Odpowiedz

11

Bo inaczej, że masz kod źródłowy, który wygląda tak:

void do_add (bigint_stack &stack) { 
    bigint right = stack.front(); 
    stack.pop_front(); 
    TRACE ('+', "right = " << right); 
    bigint left = stack.front(); 
    stack.pop_front(); 
    TRACE ('+', "left = " << left); 
    bigint result = left + (right); 
    TRACE ('+', "result = " << result); 
    stack.push_front (result); 
} 

void do_subtract (bigint_stack &stack) { 
    bigint right = stack.front(); 
    stack.pop_front(); 
    TRACE ('-', "right = " << right); 
    bigint left = stack.front(); 
    stack.pop_front(); 
    TRACE ('-', "left = " << left); 
    bigint result = left - (right); 
    TRACE ('-', "result = " << result); 
    stack.push_front (result); 
} 

Etcetera ...

Teraz, jeśli chcemy dodać kolejny ślad, na przykład, że mają ponownie skopiować i wkleić go do wszystkich.

To, czego chciał naprawdę autor, to zdefiniowanie sposobu generowania funkcji ze zbioru sparametryzowanych danych wejściowych, w taki sposób, że powstałe funkcje są do siebie podobne, ale zachowują się w nieco inny sposób w zależności od danych wejściowych generuj je. Nazywa się to metaprogramowaniem. Bardzo często w parserach kodujących, które, jak podejrzewam, pochodzą od tego fragmentu kodu.

Teraz, w innych językach, może istnieć konstrukcja specyficzna dla tego języka, aby wykonać meta-programowanie w ten sposób w bardziej przejrzysty sposób (szablony, metaklasy itp.). Ale w przypadku C makro to jest.

Powiązane problemy