¿Por qué la biblioteca C usa macros y funciones con el mismo nombre?

20

Estoy leyendo 'The Standard C Library' de PJ Plauger, que es realmente interesante. El libro explica no solo cómo USAR la biblioteca sino también cómo se implementa.

He terminado de leer la ctype.hsección y en el encabezado las funciones se declaran como macros Y funciones. Por ejemplo

int isdigit(int);

pero también

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

No entiendo por qué AMBOS se usan?

Además, si intento recrear mi propio ctypeencabezado e implementación personalizados, solo puedo compilar con éxito si elimino la macro (comente la definición).

Este aspecto no fue realmente explicado en el libro. ¿Alguien puede explicar?

usuario619818
fuente
No hay nada en el estándar C que obligue a un compilador a implementarlo como una macro. Lo más probable es que la macro sea un residuo de los viejos tiempos cuando C no tenía forro. Aunque un compilador inteligente debería poder incorporar esa función si es necesario, sin una palabra clave explícita en línea. Entonces, la macro de función solo está ahí porque el compilador fue implementado por alguien que no era brillante en la creación de compiladores.

Respuestas:

23

La macro es (supuestamente) más eficiente, ya que no implica una llamada a la función. Se puede optimizar más fácilmente, ya que solo implica una búsqueda de desplazamiento del puntero.

La llamada a la función permite vincular contra la misma biblioteca incluso si el programa se compiló sin la definición de macro, si se compiló con un encabezado diferente, o simplemente con una declaración falsa dentro del archivo fuente. Si, por ejemplo, tiene un compilador que tiene la versión "mejorada" de alguien de ctype.h que no tenía la macro, la función aún existiría en tiempo de ejecución para su uso.

Si nos fijamos en el estándar:

7.1.4 Uso de funciones de biblioteca

Cualquier función declarada en un encabezado puede implementarse adicionalmente como una macro similar a una función definida en el encabezado, por lo que si una función de biblioteca se declara explícitamente cuando se incluye su encabezado, se puede usar una de las técnicas que se muestran a continuación para garantizar que la declaración no afectado por tal macro. Cualquier definición macro de una función puede suprimirse localmente encerrando el nombre de la función entre paréntesis, porque el nombre no es seguido por el paréntesis izquierdo que indica la expansión del nombre de una función macro. Por la misma razón sintáctica, se permite tomar la dirección de una función de biblioteca incluso si también se define como una macro.

Eso significa que si escribes:

int b = (isdigit)(c);

o

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

entonces está invocando la función real, no la macro. También puedes escribir legalmente:

#undef isdigit
int b = isdigit(c);

o (en un archivo fuente que no tiene #include <ctype.h>directa o transitivamente):

extern int isdigit(int);
int b = isdigit(c);
ecatmur
fuente
¿Cómo podría compilarse el programa SIN la definición de macro?
user619818
@ user619818 usando extern int isdigit(int), por ejemplo.
ecatmur el
Solo para que quede claro, quiere decir que el usuario no tiene #include <whatever> sino que agrega int isdigit (int); en la parte superior del archivo de implementación. OK, solo lee tu respuesta correctamente.
user619818
Tener una función invocable (vs.código de macro en línea) también permite que otros lenguajes como python y perl interactúen con esas funciones
technosaurus