Asignación de macro a llamada de función
Frecuentes
Visto 1,904 equipos
1
Es posible definir una macro BREF(...):
struct bits
{
int b0:1;
int b1:1;
int b2:1;
int b3:1;
int b4:1;
int b5:1;
int b6:1;
int b7:1;
}
#define BREF(var,bit) ????
#define BAR 4
#define ALIAS BREF(foo,BAR)
unsigned char foo;
tal que esta declaración:
ALIAS = 1;
se expande a esto:
((struct bits *)&foo)->b4 = 1;
y esto:
int k = ALIAS;
a esto:
int k = ((struct bits *)&foo)->b4;
Hasta ahora, esta es mi implementación de BREF(...):
#define BREF(var,bit) (((struct bits *) &(var))->b##bit)
Sin embargo, esto solo funciona si bit
es un número literal. Quiero poder pasar una variable macro que se expanda en un número. ¿Cómo puedo hacer que el preprocesador C se expanda? bit
antes de concatenarlo b
?
2 Respuestas
3
El truco es que el preprocesador C expandirá los argumentos macro solo si no se están utilizando con el stringizing (#
) o pegar tokens (##
) operadores. Entonces, para que funcione con una macro que se expande a un literal numérico, agregue una capa adicional de macros como esta:
#define CONCAT(x, y) x ## y
#define BREF(var,bit) (((struct bits *) &(var))-> CONCAT(b, bit))
Con esta definición, bit
ya no es un argumento directo del operador de pegado de tokens, por lo que si es una macro, se expande antes de pegar el token.
Respondido 01 Jul 12, 04:07
2
Puede usar un paso adicional de expansión, como este:
#define BITATTR(num) b##num
#define BREF(var,bit) (((struct bits *) &(var))->BITATTR(bit))
Respondido 01 Jul 12, 03:07
¡Gracias, esto funciona perfectamente! He hecho stringificación con dos niveles de expansión, pero nunca concatenación. - gvl
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c macros struct bit-manipulation or haz tu propia pregunta.
Buen intento, pero el problema con este método es que el preprocesador se pega
b
yEXPAND
juntos antes de que se moleste en expandirsebit
. - gvlVaya, lo siento, tienes razón, ¡y exactamente por la razón que dije! Hice mal la prueba, pero ahora está arreglado. - adam rosenfield