Tengo un archivo de encabezado que contiene
#define PROTOTYPE(s) s
¿Cuál es el punto de esto? Parece que simplemente reemplazaría la entrada por sí mismo.
Hay un montón de otras directivas a su alrededor, pero el único que parece tener alguna relación acaba de comprobar si se define: #ifndef PROTOTYPE
. He encontrado algunos lugares en los archivos de cabecera HDF4 que hacen esto: #define PROTOTYPE
. Entonces, nada de eso realmente aclara mi pregunta. Todavía parece bastante inútil.
Así es como se usa:
CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));
Esto es parte de un proyecto que utiliza Sybase Open Client. clientmsg_callback se usa más tarde aquí:
ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
(CS_VOID *)clientmsg_callback);
Salgo de un programa de muestra de aquí:
clientmsg_callback se implementa más tarde. Creo que la muestra se escribió originalmente con C en mente, en lugar de C ++. ¿Quizás eso tenga algo que ver con eso?
#if
/#ifdef
/#ifndef
/ cercanas#else
en las que podría tener una definición diferente? Podría marcar la diferencia cuando se usa en otras macros, especialmente cerca#
o##
. Podría ser solo para un estilo de comentario. No hay suficiente contexto para responder realmente.PROTOTYPE
. Si ve definiciones extrañas en el código que parecen inútiles, piense en la flexibilidad potencial si alguien quisiera cambiar algo convenientemente.Respuestas:
En los viejos tiempos de los primeros C realmente, no existían los prototipos. Las listas de argumentos de la función venían después de los paréntesis de la función, así :
square(x) int x; { int y = x * x; return y; }
En estos días, por supuesto, los argumentos van entre paréntesis:
square(int x) { int y = x * x; return y; }
Tenga en cuenta el tipo de retorno "faltante"; Las funciones de C solían retornar implícitamente
int
, y solo si necesitaba un tipo de retorno diferente tenía que decir cuál era.Las declaraciones de funciones tenían otro conjunto de reglas. Una declaración de función en K&R C (la versión antigua) no tenía argumentos:
int square();
Y los prototipos de funciones en ANSI C tienen una lista de argumentos:
int square(int x);
Durante la transición, las personas usaron macros extravagantes para poder compilar en ambos sentidos:
int square(PROTOTYPE(int x));
Con
#define PROTOTYPE(s)
que se expandiría a la primera versión.
Con
#define PROTOTYPE(s) s
se expandiría al segundo.
Con respecto a los paréntesis "extra" en el código de la pregunta, son necesarios cuando hay más de un argumento en la lista de argumentos. Sin ellos, la invocación de la macro tiene más de un argumento, por lo que no coincidirá con una macro definida con un solo argumento:
PROTOTYPE(int x, int y) // error: too many arguments PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)
fuente
#define PROTOTYPE(s)
la entrada ? Me parece que se envuelve en una cuerda vacíaint x;
x
zlib.h
encabezado de la biblioteca zlib con laOF()
macro: github.com/madler/zlib/blob/master/zlib.hzconf.h
.Macros como esta se usarían en los prototipos en el archivo de encabezado para permitir algo como esto:
int foo PROTOTYPE((int bar));
Si se detectara ANSI C (
__STDC__
definido como 1), esto se expandiría a:int foo(int bar);
Si no se detecta ANSI C, esto se expandiría a:
int foo();
que era común antes de que C se estandarizara.
Algunas bibliotecas todavía hacen esto; si miras
tcpd.h
(si lo tienes disponible), verás:Esto lo explica bien.
En cuanto al doble paréntesis,
__P(arg1, arg2)
daría un error de sintaxis (pasando demasiados argumentos a la macro), mientras__P((arg1, arg2))
que estaría bien (solo uno entre paréntesis).Esto es similar a
__extension__((...))
GNU C. En compiladores que no son GNU, simplemente#define __extension__(unused)
para tener un código semiportátil, ya que solo se da un "argumento", entre paréntesis.fuente