Gestion de flags.

Manipulation élégante de bits.

opérateurs & et |

Voir version :

Pas de dépendances

Télécharger :

#include <stdio.h>

#define OPTION_1 1
#define OPTION_2 2
#define OPTION_3 4

void fonc(int flags)
{
    if (flags&OPTION_1)
        printf("Option 1 activee\n");
    if (flags&OPTION_2)
        printf("Option 2 activee\n");
    if (flags&OPTION_3)
        printf("Option 3 activee\n");
}

int main()
{
    fonc(OPTION_1|OPTION_3);
    return 0;
}



Commentaires


Voici une façon astucieuse de passer des flags dans une fonction sans surcharger plein de parametres.
Note : on appelle flag une valeur qui n'est que vraie ou faux (un flag est une variable sur 1 seul bit)

Regardons le main :
Le parametre passé est :

OPTION_1|OPTION_3

Tiens, si vous avez déja fait le tuto sur SDL sur ce meme site, vous avez vu qu'on passait déja des trucs comme ça :
SDL_HWSURFACE|SDL_FULLSCREEN par exemple.

Voici maintenant comment faire ce genre de fonctions :

Regardez la définition de fonc : elle n'attend qu'un seul int.
Un int, dans notre cas, c'est 32 bits (si vous etes tres a cheval sur les types qui peuvent changer en fonction du processeurs,
c'est que vous etes assez calé pour adapter vous meme)

Bref, un int, c'est 32 bits, ça peut donc - en théorie - stocker 32 flags, donc 32 options (vrai/fausses).

Voici l'astuce :
A coup de #define, on va définir nos flags, mais pas n'importe comment.
On va leur donner comme valeur : 1,2,4,8,16,32,64,128,256,512,1024,2048.... -> Que des puissances de 2.
Maximum 2^31 = 2147483648 pour 32 bits.

Pourquoi des puissances de 2 ? Parce que, en binaire cela s'écrit ainsi :

1 = 00000001
2 = 00000010
4 = 00000100
8 = 00001000
16= 00010000
32= 00100000

etc...

Du coup, et la est l'astuce : quand vous faites OPTION_1|OPTION_3, le | est bien sur le OU logique.
Et OPTION_1|OPTION_3 = 00000001|00000100 = 00000101

Vous accumulez ainsi plusieurs flags dans un seul int :)
Ainsi, vous passez a la fonction OPTION_1|OPTION_3 = 00000101 = 5.

Note : dans cette optique, un + a la place du | ferait exactement la meme chose : mais le + serait un chouia plus lent
car il testerait les retenues, chose qui n'est pas testéé pour un |, que le processeur effectue plus vite.


Récupération dans la fonction :
***************************************

Bon, maintenant, on a envoyé "5" dans la fonction fonc, on veut récupérer que c'est 1 | 4 = OPTION_1|OPTION_3

Nous nous servons de l'opérateur & avec les memes options. Ainsi, on obtiendra, soit 0 si le flag n'est pas activé,
soit nu nombre >0 si le flag est activé.

Rappelez vous que if(0) donne faux, et que if (1) ou if (x)  donne vrai (avec x>0)
Si cela vous gene, c'est absolument équivalent à :

if ((flags&OPTION_1)!=0)

Note : attention, mettez bien les parentheses, cas si vous mettez :

if (flags&OPTION_1!=0), le compilo comprendra : 
if (flags&(OPTION_1!=0))

et ça ne fera pas ce que vous attendez...

Voila cette astuce pour la gestiond de flags que je trouve élégante, et qui est surtout ultra rapide
(les opérations sur les bits comme | et & sont les plus rapides qu'un processeur sache faire...)

De plus, passer juste un int au lieu de 30 char est bien sur infiniment plus rapide.
Nous avons affaire la a une astuce qui, non content d'etre élégante, est également puissante en terme d'optimisations.

A consommer sans modérations.


Laissez un commentaire / post a comment