Definición de macro similar a una función en C

Me gustaría definir una función como MACRO. es decir

#define foo(x)\ #if x>32\ x\ #else\ (2*x)\ #endif 

es decir,

 if x>32, then foo(x) present x else, foo(x) present (2*x) 

pero mi GCC se queja de:

 int a = foo(31); 

Creo que el preprocesador C debería manejar esto correctamente. ya que en tiempo de comstackción, sabe x=33 . podría reemplazar foo(33) con (2*33)

Puede como sigue

 #define foo(x) ((x) > 32 ? (x) : (2 * (x))) 

Pero eso se evalúa x varias veces. En su lugar, puede crear una función estática, que es más limpia

 static int foo(int x) { if(x > 32) return x; return 2 * x; } 

Entonces, también puedes pasarle cosas a las personas que tienen efectos secundarios y hacer que los efectos secundarios ocurran solo una vez.

Lo que ha escrito es usar las directivas preprocesador #if , #if y #endif , pero necesita usar construcciones de lenguaje si pasa variables a la macro y desea evaluar sus valores. El uso de las instrucciones if , y else como en las construcciones de lenguaje reales tampoco funciona, porque las declaraciones de flujo de control no se evalúan a los valores. En otras palabras, una instrucción if es solo flujo de control de dirección (“si A, luego ejecute B, o ejecute C”), no evaluando ningún valor.

 #define \ foo(x) \ ({ \ int xx = (x); \ int result = (xx > 32) ? xx : (2*xx); \ result; \ }) 

Considerar:

 int x = rand() int y = foo( x ); 

x no se conoce en tiempo de comstackción.

 int a = foo(31); 

Se expande a

 int a = if 31>32 31 else (2*31) endif; 

Así es como funcionan las macros C, mediante una sustitución simple y tonta. Si espera que gcc haga algo más complejo o inteligente con ellos, su expectativa es errónea.

Dado eso, es fácil ver por qué su código no funciona. Una alternativa que sería suficiente para este ejemplo sería:

 #define foo(x) (x > 32 ? x : 2*x) 

Por otro lado, me preguntaría si las macros son realmente la herramienta adecuada para empezar. Simplemente póngalo en la función y el comstackdor insertará el código si piensa que lo acelerará.

El problema no tiene que ver con la teoría: siempre que, por algún motivo, desee tener una macro que se expanda de manera diferente según el valor de un parámetro que se le haya pasado, y este parámetro es una constante, conocida por el preprocesador de macros, no hay razón por la que no pudo funcionar … para un procesador de macros genérico … Pero cpp, desafortunadamente, no permite la presencia de otros “comandos” de procesador de macros en una definición de macro …

Entonces tus

 #define foo(x) \ #if x>32 \ x \ #else \ 2*x \ #endif 

no se expande a

 #if X>32 X #else 2*X #endif 

donde X es el parámetro conocido (por lo tanto, cambie X a, por ejemplo, 31), que requiere otra pasada por parte del preprocesador.

Además, las nuevas líneas se ignoran, mientras que son importantes para tal uso; de lo contrario, lo siguiente podría considerarse como un truco (sin embargo, se necesita otro pase de preprocesamiento)

 #define foo(x,y) \ y if x>32 \ x \ y else \ 2*x \ y endif 

que con foo(20,#) produce

 # if 20>32 20 # else 2*20 # endif 

que funcionaria, si fuera

 # if 20>32 20 # else 2*20 # endif 

… pero no lo es (y como se dijo, la salida del preprocesador debe alimentarse al preprocesador nuevamente …)

Así que mi respuesta es que si necesita estas cosas, no puede usar el preprocesador C; debería usar un preprocesador de C poco común (¿no es estándar?), o simplemente otro procesador de macros, y si necesita el tipo de cosas que “cpp” tiene que “integrarse” con C, entonces no puede usar uno genérico ( como M4) tan fácilmente …