valores tipos simples retornan que programacion parametros lenguaje funciones ejemplos con c++ c c-preprocessor conditional-compilation

c++ - tipos - Use#ifdefs y#define para convertir opcionalmente una llamada de función en un comentario



tipos de funciones en c (11)

¿Es posible hacer algo como esto?

#ifdef SOMETHING #define foo // #else #define foo MyFunction #endif

La idea es que si se define ALGO, las llamadas a foo (...) se convierten en comentarios (o algo que no se evalúa ni compila), de lo contrario se convierte en una llamada a MiFunción.

He visto usar __noop, pero no creo que pueda usar eso.

EDIT (s):

No creo que realmente pueda usar una macro aquí, porque MyFunction toma una cantidad variable de argumentos.

Además, me gustaría hacerlo para que los argumentos NO sean evaluados! (Así que hacer algo como comentar el cuerpo de MyFunction realmente no me da lo que necesito, ya que los argumentos aún se evaluarán)


¿Qué hay de algo en esta línea?

#ifdef NDEBUG #define DEBUG(STATEMENT) ((void)0) #else #define DEBUG(STATEMENT) (STATEMENT) #endif

Lo usaría así para registrar mensajes de depuración:

DEBUG(puts("compile with -DNDEBUG and I''m gone"));

Una versión no genérica para salida formateada con información de depuración adicional usando macros variadic C99 y el identificador __func__ podría verse así:

#ifdef NDEBUG #define Dprintf(FORMAT, ...) ((void)0) #define Dputs(MSG) ((void)0) #else #define Dprintf(FORMAT, ...) / fprintf(stderr, "%s() in %s, line %i: " FORMAT "/n", / __func__, __FILE__, __LINE__, __VA_ARGS__) #define Dputs(MSG) Dprintf("%s", MSG) #endif

Así es como usaría estas macros:

Dprintf("count = %i", count); Dputs("checkpoint passed");


¿Qué hay de rodear cada llamada a miFunción con

#ifdef SOMETHING myFunction(...); #endif

?


¿Quizás una forma más fácil de hacer esto sería omitir condicionalmente el cuerpo de la función?

void MyFunction() { #ifndef SOMETHING <body of function> #endif }

A menos que específicamente no desee que se realice una llamada de función, esto parece una forma limpia de lograr su objetivo.


Es probable que no desee hacer la simple "eliminación de código" como se sugiere, porque las personas que llaman esperarán que ocurran los efectos secundarios de los argumentos. Aquí hay algunos fragmentos de llamadas problemáticos que deberían hacerte pensar:

// pre/post increment inside method call: MyFunction(i++); // Function call (with side effects) used as method argument: MyFunction( StoreNewUsernameIntoDatabase(username) );

Si fuera a deshabilitar MyFunction simplemente diciendo:

#define MyFunction(x)

entonces los efectos secundarios que esperaban los llamadores se irían, y su código se rompería, y sería bastante difícil de depurar. Me gusta la sugerencia "sizeof" anterior, y también me gusta la sugerencia de simplemente deshabilitar el cuerpo de MyFunction () a través de # ifdef, aunque eso significa que todas las personas que llaman obtienen la misma versión de MyFunction (). De su declaración del problema, supongo que no es realmente lo que quiere.

Si realmente necesita deshabilitar MyFunction () a través de las definiciones del preprocesador por archivo de origen, entonces lo haría así:

#ifdef SOMETHING #define MyFunction(x) NoOp_MyFunction(x) int NoOp_MyFunction(x) { } #endif

Incluso podría incluir la implementación de NoOp_MyFunction () dentro de la fuente y los encabezados de MyFunction (). También tiene la flexibilidad de agregar información adicional de registro o depuración en NoOp_MyFunction () también.


Lamentablemente, la versión actual de C ++ no admite macros variadic.

Sin embargo, puedes hacer esto:

#ifdef SOMETHING #define foo #else #define foo(args) MyFunction args #endif // you call it with double parens: foo((a, b, c));


No, los estándares de C y C ++ dicen que no se puede #definir algo para que sea un comentario, por lo que

#define foo //

no funcionará


Si mal no recuerdo, deberías poder # definir tu macro a "nada" y eso hará que el compilador ignore esa llamada

#define foo() foo(); // this will be ignored


Si, en el caso de que no desee llamar a foo, lo define como:

void foo() {}

cualquier llamada a foo () debería ser optimizada.


#ifdef SOMETHING #define foo sizeof #else #define foo MyFunction #endif

¿Asumo que foo es una printf estilo printf ? De todos modos, esto no funcionará con una función de parámetro cero, pero si ese fuera el caso, ya sabrías qué hacer. Si realmente quieres ser anal puedes usar (void)sizeof pero eso probablemente sea innecesario.


Soy un poco reacio a publicar esta respuesta porque el uso de hackers macro puede convertirse en la fuente de problemas. Sin embargo, si las llamadas a la función que quiere que desaparezcan siempre se usan solos en una declaración (es decir, nunca forman parte de una expresión más grande), entonces algo como lo siguiente podría funcionar (y maneja varargs):

#ifdef SOMETHING #define foo (1) ? ((void) 0) : (void) #else #define foo MyFunction #endif

Entonces, si tienes la línea de código:

foo( "this is a %s - a++ is %d/n", "test", a++);

terminará después del paso de preproceso como:

MyFunction( "this is a %s - a++ is %d/n", "test", a++);

o

(1) ? ((void) 0) : (void)( "this is a %s - a++ is %d/n", "test", a++);

que convierte la lista de parámetros de la pseudo-función en un grupo de expresiones separadas por el operador de coma que nunca será evaluado, ya que el condicional siempre devuelve el resultado ((void) 0) .

Una variante de esto es algo cercano a lo que ChriSW y Jonathan Leffler sugirieron:

#ifdef SOMETHING #define foo if (0) MyFunction #else #define foo if (1) MyFunction #endif

Esto es ligeramente diferente, ya que no requiere que el compilador admita macros __VA_ARGS__ ( __VA_ARGS__ ).

Creo que esto puede ser útil para eliminar llamadas de función de seguimiento de depuración que generalmente nunca se combinan en una expresión más grande, pero más allá de eso, creo que es una técnica peligrosa.

Tenga en cuenta la posibilidad de problemas, especialmente si los parámetros de la llamada producen efectos secundarios (este es un problema general con las macros, no solo este truco). En el ejemplo, a++ se evaluará solo si SOMETHING está definido en la compilación, de lo contrario no lo es. Entonces, si el código después de la llamada depende del valor de a para ser incrementado, una de las compilaciones tiene un error.


Prueba esto:

#ifdef SOMETHING #define foo(x) #else #define foo(x) MyFunction(x) #endif

Si su función tiene varios argumentos, entonces:

#ifdef SOMETHING #define foo(x,y,z) #else #define foo(x,y,z) MyFunction(x,y,z) #endif

Si su función tiene una cantidad variable de argumentos, entonces su compilador puede soportar las llamadas "macros variadic", como esta:

#ifdef SOMETHING #define foo(...) #else #define foo(...) MyFunction(__VA_ARGS__) #endif

La razón por la que he visto este tipo de cosas usadas en la práctica es deshacerse de las funciones de registro de una compilación de lanzamiento. Sin embargo, consulte también las versiones separadas de ''depuración'' y ''liberación''? en el que las personas se preguntan si incluso deberían tener versiones diferentes.

Alternativamente, en lugar de redefinir la llamada a la función como nada, el comentario de Jonathan a esta respuesta sugirió hacer algo como lo siguiente:

#ifdef SOMETHING #define foo(...) do { if (false) MyFunction(__VA_ARGS__) } while (0) #else #define foo(...) do { if (true) MyFunction(__VA_ARGS__) } while (0) #endif

El razonamiento para hacer esto es para que la llamada a la función siempre se compile (para que no quede con errores gratuitos como referencias a variables eliminadas), sino que solo se llama cuando sea necesario: ver Kernighan & Pike The Practice of Programming y también The Goddard Estándares de programación de Space Flight Center .

Desde un archivo debug.h (originado en 1990, y por lo tanto no usando __VA_ARGS__ ):

/* ** Usage: TRACE((level, fmt, ...)) ** "level" is the debugging level which must be operational for the output ** to appear. "fmt" is a printf format string. "..." is whatever extra ** arguments fmt requires (possibly nothing). ** The non-debug macro means that the code is validated but never called. ** -- See chapter 8 of ''The Practice of Programming'', by Kernighan and Pike. */ #ifdef DEBUG #define TRACE(x) db_print x #else #define TRACE(x) do { if (0) db_print x; } while (0) #endif /* DEBUG */

Con C99, ya no es necesario el truco de doble paréntesis. El nuevo código no debe usarlo a menos que la compatibilidad con C89 sea un problema.