El operador ## en C

¿Qué hace ## en C?

Ejemplo:

 typedef struct { unsigned int bit0:1; unsigned int bit1:1; unsigned int bit2:1; unsigned int bit3:1; unsigned int bit4:1; unsigned int bit5:1; unsigned int bit6:1; unsigned int bit7:1; } _io_reg; #define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bit##bt 

(Sé lo que hace todo además de la parte ##).

Es la concatenación de cadenas , como parte de la macro del preprocesador.

(En este contexto, “cadena” se refiere a un token de preprocesador, por supuesto, o una “cadena de código fuente”, y no una cadena en C).

Se llama el operador de pegado; concatena el texto en bt con el bit texto. Así, por ejemplo, si tu invocación de macro fue

 REGISTER_BIT(x, 4) 

Se expandiría a

 ((volatile _io_reg*)&x)->bit4 

Sin él, no podría poner un argumento de macro directamente al lado del texto en el cuerpo de la macro, porque entonces el texto tocaría el nombre del argumento y se convertiría en parte del mismo token, y se convertiría en un nombre diferente.

El operador ## concatena dos argumentos sin dejar espacios en blanco entre ellos:

 #define glue(a,b) a ## b glue(c,out) << "test"; 

Ese es el operador de pegado de fichas .

Eso es parte de la definición de la macro.

Te permite concatenar cadenas dentro de la macro.

En su caso, puede usar bt de 7 a 0 de esta manera:

 REGISTER_BIT(myreg, 0) 

y se ampliará como:

((volatile _io_reg*)& myreg )->bit 0

Sin esto, tendrías que definir la parte de bit de la macro como uno de los argumentos de la macro:

 #define REGISTER_BIT(rg,bt) ((volatile _io_reg*)&rg)->bt 

donde el uso sería:

 REGISTER_BIT(myreg, bit0) 

que es más engorroso.

Esto también te permite construir nuevos nombres.

Supongamos que tiene estas macros:

 #define AAA_POS 1 #define AAA_MASK (1 << AAA_POS) #define BBB_POS 2 #define BBB_MASK (1 << BBB_POS) 

y desea una macro que extraiga AAA de un vector de bits. Puedes escribirlo así:

 #define EXTRACT(bv, field) ((bv & field##_MASK) >> field##_POS) 

y luego lo usas así:

 EXTRACT(my_bitvector, AAA) 

No es una construcción en C, es una característica del preprocesador . En este caso, se pretende evaluar la variable bt y concatenarla con el prefijo de bit . Sin los hashes tendrías bitbt allí, lo que obviamente no funcionaría.

Aquí hay un ejemplo de ffmpeg , una macro que registra filtros de audio y video:

 #define REGISTER_FILTER(X, x, y) \ { \ extern AVFilter ff_##y##_##x; \ if (CONFIG_##X##_FILTER) \ avfilter_register(&ff_##y##_##x); \ } 

y el uso puede ser:

 REGISTER_FILTER(AECHO,aecho,af); REGISTER_FILTER(VFLIP,vflip,vf);