2012-02-08 5 views
25

Jeśli zdefiniuję makro funkcji bez rzeczywistej funkcji, czy jest to pusty ciąg z kompilatorem (tzn. Nie generuje żadnych dodatkowych instrukcji podczas kompilacji)?Puste makra funkcji

przykład:

#define SomeMacro(a) 

SomeMacro("hello"); // This line doesn't add any instructions, does it? 

Odpowiedz

32

Masz całkowitą rację, puste makro nie generuje żadnego kodu.

Widziałem dwa miejsca, w których jest to przydatne. Pierwszą jest wyeliminowanie ostrzeżeń, gdy parametr funkcji nie jest używany:

#define UNUSED(x) 

int foo(int UNUSED(value)) 
{ 
    return 42; 
} 

Drugi to podczas korzystania warunkowe celu ustalenia, czy nie powinno być kod czy nie.

#ifdef LOGGING_ENABLED 
#define LOG(x) log_message(x) 
#else 
#define LOG(x) 
#endif 
+0

to jest bardzo przydatna odpowiedź, myślę, że dobra robota ;) – GameDeveloper

+0

Cześć Nie rozumiem twojego pierwszego kodu [tutaj próbowałem] (http://codepad.org/WbSlIXkc) .. Myślę, że to po prostu błąd zapisu 'int foo (int UNUSED (wartość)) jeśli definicja makra to balan **? ** –

+3

@GrijeshChauhan, właśnie odkryłeś jedną z różnic między C i C++. Zobacz tutaj: http://codepad.org/flX8m3sk –

5

preprocesor wykonuje dosłownego podstawienie wszystkich makr.

Dlatego jeśli zdefiniujesz makro "puste", to każde miejsce, w którym identyfikator pojawi się w twoim kodzie, zostanie zastąpione pustą instrukcją przez preprocesor, zanim kompilator kiedykolwiek uruchomi się.

Tak, tak. Żaden kod nie zostanie wygenerowany dla przykładu podanego w pytaniu.

6

Zgadza się. Po przetwarzaniu wstępnym kod rozszerza się do

; 

.

pamiętać, że można zwrócić się do kompilatora, aby pokazać Ci kod po wyprzedzającym (w gcc, jest to opcja -E; kompilator może się zmieniać).

+0

kod nie generować cokolwiek, nawet średnik. (zweryfikowane przy użyciu gcc 4.5.2) – shinkou

+4

@shinkou, średnik jest poza makrem, więc powinien być częścią ostatecznego kodu –

13

Twój kod nie jest całkowicie poprawna, proponuję umieścić pustych nawiasów w makro

#define somemacro(a) {} 

Powód jest prosty, to kod będzie znacznie bardziej bezpieczny!

wziąć ten przykład:

if(Value) 
    somemacro(a) 
else 
    somemacro(b) 

Jeśli makro jest pusty Twój kod nie będzie kompilować! (Oczekiwany pierwotny-expressione przed "innym"). W każdym razie niektóre reguły stylu zmuszają Cię do napisania tego obiektu, więc nie będzie to stanowić problemu.

Inną opcją jest użycie ";" zamiast "{}", ale ta opcja w tym samym przypadku da ci ostrzeżenia dotyczące czasu kompilacji, podczas gdy puste nawiasy nie będą dawały ostrzeżeń ani błędów! (Średnik jest jeszcze lepiej, nawet jeśli dają ostrzeżenia);)

odbioru następujący przypadek

if(value) 
    somemacro(a); 
else 
    somemacro(b); 

wzrośnie do

if(value) 
{}; 
else 
{}; 

że nie można skompilować!

Dlatego makra są złe

(ponieważ makra są proste tekstu wymiana, rządy dumbs powinno być zawsze próbować ręcznie zastąpić kod i zobaczyć co się dzieje, są też narzędzia, które zastąpią makra wyświetlasz rozszerzony kod.)

Nadal zgadujesz, czy istnieje makro, które jest całkowicie bezpieczne? Tak to się nazywa „NOP”

#define somemacro(a) ((void)0) 

że zadziała w każdym przypadku (nawet pliki źródłowe kompilatory użyć jej jako NOP, na przykład wystarczy spojrzeć na „assert.h”

+4

Dokładnie zamierzano pokazać najbardziej poprawne użycie makr. puste makro funkcji nie może być nadal używane w niektórych przypadkach. Tak więc każdy przypadkowy użytkownik czytający post musi mieć świadomość, że używanie "((void) 0)" jest lepszym wyborem. W każdym razie to jest "NOP", ale nie NOP. infact nie jest generowany dodatkowy zestaw dla ((void) 0), podczas gdy instrukcja NOP jest nadal zbiorem. Zawsze należy brać pod uwagę bezpieczeństwo kodu. Wciąż nie ma powodu do kciuka w dół. – GameDeveloper

+0

Wycofano, ponieważ jest to jedyna odpowiedź na temat niewłaściwego użycia - choć prawdopodobnie nacisk powinien zostać przeniesiony bezpośrednio do ((void) 0). Dla tych, którzy twierdzą, że to jest niepotrzebne (@Qix), sprawdź [bardzo podręcznik GCC] (https://gc.gnu.org/onlinedocs/cpp/Macro-Pitfalls.html#Macro-Pitfalls). – hmijail

+1

Um ... Dokładnie to jest to, do czego służy 'do {} while (0)' idiom. Używanie zwykłego '{}' w tym celu nie jest dobrym pomysłem, ponieważ wymaga od użytkownika, aby pamiętać, aby NIE wstawiać ';' po tym wywołaniu makra. – AnT