2012-12-15 7 views

Odpowiedz

38

To po prostu makro, które rozszerza się, no cóż, nic. Jednak teraz, gdy makro zostało zdefiniowane, możesz sprawdzić, czy jest ono zdefiniowane, czy nie.

#define FOO 

int main(){ 
    FOO FOO FOO 
    printf("Hello world"); 
} 

wzrośnie do

int main(){ 

    printf("Hello world"); 
} 

Istnieją pewne sytuacje, w których ta jest bardzo przydatna, na przykład dodatkowe informacje debugowania, które nie chcą, aby pokazać w wersji wydania:

/* Defined only during debug compilations: */ 
#define CONFIG_USE_DEBUG_MESSAGES 

#ifdef CONFIG_USE_DEBUG_MESSAGES 
#define DEBUG_MSG(x) print(x) 
#else 
#define DEBUG_MSG(x) do {} while(0) 
#endif 

int main(){ 
    DEBUG_MSG("Entering main"); 
    /* ... */ 
} 

Ponieważ makro CONFIG_USE_DEBUG_MESSAGES zostało zdefiniowane, DEBUG_MSG(x) rozwinie się na print(x), a otrzymasz Entering main. Jeśli usuniesz #define, DEBUG_MSG(x) rozwinie się do pustej pętli i nie zobaczysz komunikatu.

+1

Jest to bardzo ryzykowne, ponieważ może uszkodzić kompilację, szczególnie. gdy masz zdania typu '' 'if (x) DEBUG_MSG (" test "); else DEBUG_MSG ("test"); "' '. Wolę zadeklarować moje puste makro z niewypełnioną instrukcją, jak '' '#define DEBUG_MSG (x) do {} while (0)' '' – Ely

+0

@ Ely lepszym przykładem jest osłona nagłówka. Tak czy inaczej, naprawione. – Zeta

15

Tak, puste zdefiniowanie jest dozwolone przez standard.

C11 (n1570), § 6.10 przerób dyrektyw

control-line: 
    # define identifier replacement-list new-line 
    # define identifier lparen identifier-list(opt)) replacement-list new-line 
    # define identifier lparen ...) replacement-list new-line 
    # define identifier lparen identifier-list , ...) replacement-list new-line 
replacement-list: 
    pp-tokens(opt) 

Wspólne wykorzystanie jest straż integracji.

#ifndef F_H 
# define F_H 

#endif 
+0

Nie odpowiedziałeś, jaka jest wartość 'FOO' po pustym zdefiniowaniu. –

+3

@ user14284 Makra nie mają wartości. Rozbudowują się do listy tokenów. Ta lista może być pusta. – melpomene

1

Definicje pustych makr można również wykorzystać do samodzielnej dokumentacji. Numer IN w poniższym fragmencie kodu to przykład. Kod i komentarz są cytowane z EDK II project.

// 
// Modifiers for Data Types used to self document code. 
// This concept is borrowed for UEFI specification. 
// 

/// 
/// Datum is passed to the function. 
/// 
#define IN 


typedef 
EFI_STATUS 
(EFIAPI *EFI_BLOCK_RESET)(
    IN EFI_BLOCK_IO_PROTOCOL   *This, 
    IN BOOLEAN      ExtendedVerification 
); 
+0

Chciałbym użyć innego przykładu. Nie musi to być cytat z rzeczywistego kodu, ale obecny przykład zawiera dość dużą ilość niepotrzebnych informacji. (Przy okazji, upewnij się, że twoja odpowiedź wciąż odpowiada na oryginalne pytanie, działa dobrze z innymi odpowiedziami, ale jako samodzielna odpowiedź nie pasuje do pytania "Co robi" FOO "do"? "). – Zeta

+0

Dzięki za wskazanie. Po prostu czytałem ten fragment kodu, kiedy widzę to pytanie. Ponieważ odpowiedź została wybrana od dawna, mam tylko nadzieję, że moja odpowiedź może służyć jako referencja edukacyjna. – smwikipedia

Powiązane problemy