Perché la libreria C utilizza macro e funzioni con lo stesso nome?

20

Sto leggendo "The Standard C Library" di PJ Plauger che è davvero interessante. Il libro spiega non solo come utilizzare la libreria ma anche come è implementata.

Ho finito di leggere la sezione ctype.h e nell'intestazione le funzioni sono dichiarate come entrambe le macro E funzioni. Ad esempio

int isdigit(int);

ma anche

#define isdigit(c) (_Ctype[(int)(c)] & _DI)

Non capisco perché ENTRAMBI sono usati?

Inoltre, se provo a ricreare la mia intestazione ctype personalizzata e l'implementazione, posso compilare correttamente solo se rimuovo la macro (commenta la definizione).

Questo aspetto non è stato davvero spiegato nel libro. Qualcuno può spiegare, per favore?

    
posta user619818 07.08.2012 - 14:10
fonte

1 risposta

23

La macro è (putativamente) più efficiente, in quanto non implica una chiamata di funzione. Può essere ottimizzato più facilmente, poiché implica solo una ricerca offset puntatore.

La chiamata alla funzione consente il collegamento alla stessa libreria anche se il programma è stato compilato senza la definizione della macro - se è stato compilato con un'intestazione diversa o solo con una dichiarazione non valida all'interno del file sorgente. Se, ad esempio, hai un compilatore che ha la versione "migliorata" di ctype.h di qualcuno che non ha ha la macro, la funzione dovrebbe ancora esistere in fase di runtime per l'uso.

Se osserviamo lo standard:

7.1.4 Use of library functions

Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.

Ciò significa che se scrivi:

int b = (isdigit)(c);

o

int (*f)(int) = &isdigit;
int b = f(c);

quindi stai invocando la funzione effettiva, non la macro. Puoi anche scrivere legalmente:

#undef isdigit
int b = isdigit(c);

o (in un file di origine che non ha #include <ctype.h> direttamente o in transito):

extern int isdigit(int);
int b = isdigit(c);
    
risposta data 07.08.2012 - 14:19
fonte

Leggi altre domande sui tag