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:
c99
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);