L’opérateur ## en C

Que fait ## en C?

Exemple:

 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 

(Je sais ce que tout fait à part la partie ##.)

Il s’agit d’ une concaténation de chaînes faisant partie de la macro du préprocesseur.

(Dans ce contexte, “chaîne” désigne un jeton de préprocesseur, bien sûr, ou une “chaîne de code source”, et non une chaîne de caractères.)

C’est ce qu’on appelle l’opérateur de collage; il concatène le texte dans bt avec le bit texte. Ainsi, par exemple, si votre invocation de macro était

 REGISTER_BIT(x, 4) 

Il serait étendu à

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

Sans lui, vous ne pourriez pas placer d’argument de macro directement à côté de texte dans le corps de la macro, car le texte toucherait alors le nom de l’argument et ferait partie du même jeton et deviendrait un nom différent.

L’opérateur ## concatène deux arguments en ne laissant aucun espace entre eux:

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

C’est l’ opérateur de collage de jetons .

Cela fait partie de la définition de la macro.

Il vous permet de concaténer des chaînes dans la macro.

Dans votre cas, vous pouvez utiliser bt de 7 à 0 comme ceci:

 REGISTER_BIT(myreg, 0) 

et il sera élargi comme suit:

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

Sans cela, vous devez définir la partie bit de la macro comme l’un des arguments de la macro:

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

où l’utilisation serait:

 REGISTER_BIT(myreg, bit0) 

ce qui est plus lourd.

Cela vous permet également de créer de nouveaux noms.

Supposons que vous ayez ces macros:

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

et vous voulez une macro qui extrait AAA d'un vecteur de bits. Vous pouvez l'écrire comme ceci:

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

et puis vous l'utilisez comme ceci:

 EXTRACT(my_bitvector, AAA) 

Ce n’est pas une construction C, c’est une fonctionnalité de préprocesseur . Dans ce cas, il s’agit d’évaluer la variable bt et de la concaténer avec le préfixe de bit . Sans les hachages, vous auriez du bitbt , ce qui ne fonctionnerait évidemment pas.

Voici un exemple tiré de ffmpeg , une macro qui enregistre les filtres audio et vidéo:

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

et l’utilisation peut être:

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