2013-01-22 21 views
15

czytałem o __noop i przykład MSDN jestDlaczego i kiedy używać __noop?

#if DEBUG 
    #define PRINT printf_s 
#else 
    #define PRINT __noop 
#endif 

int main() { 
    PRINT("\nhello\n"); 
} 

i nie widzę przyrost ciągu tylko o puste makro:

#define PRINT 

Wygenerowany kod jest taki sam. Jaki jest prawidłowy przykład użycia __noop, który faktycznie sprawia, że ​​jest przydatny?

+0

Sądzę, że są sytuacje, w których "brak instrukcji" zmienia sposób działania. Nie jestem do końca pewien, czy mogę teraz o tym pomyśleć ". –

+2

Btw, ich przykład jest nieco podejrzany, ponieważ powoduje wyrażenie z innym typem w trybie debugowania i zwolnienia. Ale nie jest tak podejrzany, jak typ w trybie debugowania, niezależnie od "argumentów" do "PRINT"! Makra Variadic pozwalają na lepiej zachowaną definicję '#define PRINT (...) ((void) printf_s (__ VA_ARGS __))' i '#define PRINT (...) ((void) 0)', która również zatrzymuje Cię próbuje wziąść wskaźnik funkcji za pomocą '& PRINT'. –

Odpowiedz

15

The __noop wewnętrznych określa, że ​​funkcja powinna być ignorowana i listy argumentów być analizowany ale żaden kod generowany dla argumentów. Jest przeznaczony do użycia w globalnych funkcjach debugowania, które pobierają zmienną liczbę argumentów.

W twoim przypadku argumentem jest oczywiście wyraz wolny od skutków ubocznych, który można łatwo zoptymalizować, więc nie ma to znaczenia.

Ale jeśli wyrażenie argumentu ma efekty uboczne lub jest tak skomplikowane, że kompilator nie może udowodnić, że kończy się normalnie i nie ma skutków ubocznych, użycie __noop zapobiega potencjalnie kosztownej ocenie tego wyrażenia.

Drugą korzyścią jest to, że zachowuje się jak wywołanie funkcji ze zmienną liczbą argumentów składniowo. Zastąpienie go wywołaniem funkcji nie ma wpływu na parsowanie programu. Z niektórymi innymi zamiennikami (takimi jak pusty ciąg), może to być problem w niektórych sytuacjach.

+0

Tak, myślę, że to jest to. :) –

12
#define PRINT 
extern int some_complicated_calculation(); 
PRINT("%d\n", some_complicated_calculation()); 

zadzwoniłby tę funkcję, nawet jeśli nie chcesz uzyskać wyniku.

Za pomocą __noop funkcja nie zostanie wywołana.

Można (zakładając, że kompilator obsługuje makra variadic) zdefiniuj PRINT, aby zignorować argumenty; ale wtedy nie będą one w ogóle analizowane i mogą stać się nieważne, jeśli zmienimy kod wokół nich bez kompilacji wariantu, który definiuje, aby coś zrobić. Używając argumentu __noop, argumenty są nadal analizowane, więc są bardziej prawdopodobne, że pozostaną prawidłowe.

Powiązane problemy