Macro y función con el mismo nombre

4 minutos de lectura

avatar de usuario
Yousf

Tengo el siguiente código

#define myfunc(a,b) myfunc(do_a(a), do_b(b))

void myfunc(int a, int b)
{
  do_blah(a,b);
}
int main()
{
    int x = 6, y = 7;
    myfunc(x,y);

    return 0;
}

Quiero que el preprocesador amplíe la función myfunc solo al llamar. El código requerido después del preprocesamiento se ve así:

void myfunc(int a, int b)
{
  do_blah(a,b);
}
int main()
{
    int x = 6, y = 7;
    myfunc(do_a(x),do_b(y));

    return 0;
}

El problema es que la definición de la función también se expande así.

void myfunc(do_a(int a), do_b(int b))
{
  do_blah(a,b);
}

¿Hay alguna forma de hacer que la macro se expanda solo si estamos expandiendo una llamada de función? Intenté muchas soluciones, y parece imposible, pero espero que alguien haya visto una situación como esta.

NOTA: por favor, no me digas que cambie el nombre de la macro o los nombres de las funciones: D

Update1: Gracias por tu ayuda. Pero solo puedo cambiar la definición de la macro, no puedo cambiar su posición y no puedo cambiar la implementación de la función.

avatar de usuario
pmg

Utilizar () para evitar que el preprocesador expanda la definición de la función:

#include <stdio.h>

#define myfunc(a, b) myfunc(do_a(a), do_b(b))
/* if you have a preprocessor that may be non-standard
 * and enter a loop for the previous definition, define
 * myfunc with an extra set of parenthesis:
#define myfunc(a, b) (myfunc)(do_a(a), do_b(b))
 ******** */

int (myfunc)(int a, int b) /* myfunc does not get expanded here */
{
    printf("a=%d; b=%d\n", a, b);
    return 0;
}

int do_a(int a)
{
    return a * 2;
}

int do_b(int b)
{
    return b - 5;
}

int main(void)
{
    myfunc(4, 0);
    return 0;
}

  • Creo que algunos preprocesadores pueden resistirse al uso recursivo de la forma myfunc(xxx,xxx). Haría #define myfunc(a,b) (myfunc)(do_a(a), do_b(b)) int (myfunc)(int a, int b) &c

    –Tim Schaeffer

    23 de diciembre de 2009 a las 17:39

  • ¡Buen punto, Tim, gracias! Pero creo que es seguro asumir que el preprocesador nunca entrará en un bucle recursivo (cf Standard 6.10.3.4/2 “… si algún reemplazo anidado encuentra el nombre de la macro que se reemplaza, no se reemplaza…”).

    – pmg

    23 de diciembre de 2009 a las 18:11

  • Si puede cambiar la función para poner () alrededor de su nombre, ¿por qué no puede cambiar el nombre de la función?

    –Pete Kirkham

    23 de diciembre de 2009 a las 23:20

  • También me he estado preguntando sobre eso, pero no tuve las agallas para hacer la pregunta directamente 🙂

    – pmg

    23 de diciembre de 2009 a las 23:36

  • Para cambiar el nombre de la función, debe: obtener la aprobación de todos los gerentes, actualizar todos los documentos, volver a ejecutar los casos de prueba

    – Yousf

    24 de diciembre de 2009 a las 6:16

Veo tres posibles soluciones:

  • defina su macro después de la definición de la función.

  • define, antes de la definición de la función, do_a() y do_b() de modo que devuelvan su argumento y los redefinan a su voluntad después de la definición de la función

  • llevar a cabo do_a() y do_b() dentro de la función:

    void myfunc(int a, int b)
    {
        do_blah(do_a(a),do_b(b));
    }
    

Tengo una fuerte preferencia por este último.

Definir la macro después la definición de la función.

void myfunc(int a, int b)
{
  do_blah(a,b);
}

#define myfunc(a,b) myfunc(do_a(a), do_b(b))

int main()
{
    int x = 6, y = 7;
    myfunc(x,y);

    return 0;
}

Defina la macro después de definir la función.

Alternativamente, use un patrón como este:

#define myfunc_macro(a,b) myfunc(do_a(a), do_b(b))
#define myfunc(a,b) myfunc_macro(a,b)

.
.

#undef myfunc
void myfunc(int a, int b)
{
  do_blah(a,b);
}
#define myfunc(a,b) myfunc_macro(a,b)

.
.

int main()
{
    int x = 6, y = 7;
    myfunc(x,y);

    return 0;
}

¿Por qué no puedes cambiar el código fuente? En el peor de los casos, si necesita mantener la versión original, ejecute una parche en él para crear un archivo temporal en el que se cambia el nombre de la función y construirlo desde allí.

  • es un código heredado … cambiar los nombres de funciones o macros no es una opción.

    – Yousf

    23 de diciembre de 2009 a las 13:58

  • Es simplemente imposible que puedas cambiar la macro y no la función. Es simplemente imposible que pueda compilar un archivo pero no elegir qué archivo compilar. Estás hablando basura.

    –Pete Kirkham

    23 de diciembre de 2009 a las 15:04

  • es un código heredado … cambiar los nombres de funciones o macros no es una opción.

    – Yousf

    23 de diciembre de 2009 a las 13:58

  • Es simplemente imposible que puedas cambiar la macro y no la función. Es simplemente imposible que pueda compilar un archivo pero no elegir qué archivo compilar. Estás hablando basura.

    –Pete Kirkham

    23 de diciembre de 2009 a las 15:04

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad