Asignación de macro a llamada de función

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?

preguntado el 01 de julio de 12 a las 03:07

2 Respuestas

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

Buen intento, pero el problema con este método es que el preprocesador se pega b y EXPAND juntos antes de que se moleste en expandirse bit. - gvl

Vaya, lo siento, tienes razón, ¡y exactamente por la razón que dije! Hice mal la prueba, pero ahora está arreglado. - adam rosenfield

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 or haz tu propia pregunta.