Wieloliniowe makra preprocesora

81

Jak zrobić makro preprocesora wieloliniowego? Wiem, jak zrobić jedną linię:

#define sqr(X) (X*X)

ale potrzebuję czegoś takiego:

#define someMacro(X)
    class X : public otherClass
    {
         int foo;
         void doFoo();
    };

Jak to działa?

To jest tylko przykład, rzeczywiste makro może być bardzo długie.

hałaśliwy kot
źródło
Możesz łatwo uzyskać odpowiedź, wyszukując SO. np. stackoverflow.com/questions/4007865/…
Forever Learner
różne metody są tutaj: parashift.com/c++-faq/macros-with-multi-stmts.html
Ayrat,
Związane z: stackoverflow.com/questions/98944/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

123

Używasz \jako znaku ucieczki kontynuacji linii.

#define swap(a, b) {               \
                       (a) ^= (b); \
                       (b) ^= (a); \
                       (a) ^= (b); \
                   }

EDYCJA: Jak @abelenky zauważył w komentarzach, \znak musi być ostatnim znakiem w linii . Jeśli tak nie jest (nawet jeśli później jest to po prostu spacja), w każdym kolejnym wierszu pojawią się mylące komunikaty o błędach.

Ed S.
źródło
44
Uwaga: upewnij się, że \ jest ostatnim znakiem w wierszu. W C białe znaki zazwyczaj nie mają znaczenia, ale w tym przypadku niewidoczne białe znaki na końcu linii mogą cię zabić.
abelenky
2
Należy jednak dodać, że wynikowy tekst znajduje się w jednej linii. Ponieważ C traktuje wszystkie białe znaki między żetonami tak samo, zwykle nie ma to większego znaczenia, ale nadal.
Peter - Przywróć Monikę
Inną rzeczą, którą proponuję zrobić, jest umieszczenie ` after all useful lines of the macro, and add a comment afterward saying something like // pustej linii wymaganej po makrze . It's sometimes easier to ensure that all lines of a macro end with `, niż upewnienie się, że tak zrobi wszystko oprócz ostatniej.
supercat
Nie wiedziałem, że możesz użyć bitowego xor w ten sposób do zamiany zmiennych, ale żałuję, że nie miałem tego !!!
cmarangu
18

Możesz ustawić makro w wielu wierszach, umieszczając odwrotny ukośnik ( \) na końcu każdego wiersza:

#define F(x) (x)   \
              *    \
             (x)
Kerrek SB
źródło
18

PROSZĘ PAMIĘTAĆ, jak wskazali Kerrek SB i Coaddict, na co należało zwrócić uwagę w przyjętej odpowiedzi, ZAWSZE umieszczajcie nawiasy wokół argumentów. Przykład sqr jest prostym przykładem nauczanym na kursach CompSci.

Oto problem: jeśli zdefiniujesz to w ten sposób, co się dzieje, gdy mówisz „sqr (1 + 5)”? Otrzymujesz „1 + 5 * 1 + 5” lub 11
Jeśli prawidłowo umieścisz wokół niego nawiasy klamrowe, #define sqr(x) ((x)*(x))
otrzymasz ((1 + 5) * (1 + 5)) lub to, czego chcieliśmy 36 ... piękne.

Ed S. będzie miał ten sam problem z „zamianą”

jiveturkey
źródło
co powiesz na to sqr(++i)? (załóżmy, że mamy int i) :)
Géza Török
Zrobiłem to jako ćwiczenie i najwyraźniej ijest zwiększane, gdy jest podstawiane do makra (w tym przypadku jest podstawiane dwukrotnie), a następnie jest mnożone. A więcsqr(++5) == ((7) * (7))
jiveturkey
2
@ GézaTörök Rozwinięcie sqr(++i)to ((++i)*(++i))wywołałoby niezdefiniowane zachowanie, ponieważ wartość ijest modyfikowana więcej niż raz w tej instrukcji (brak punktu sekwencji między operacjami).
moooeeeep
5

Musisz opuścić nową linię na końcu linii, poprzedzając ją znakiem \:

#define sqr(X) \
        ((X)*(X))
codaddict
źródło