[TUTO] Utiliser les flags

Informations pour bien débuter en PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

[TUTO] Utiliser les flags

Message par microdevweb »

Bonjour à tous,

Les flags (drapeaux, en français) sont largement utilisés par les fonctions de PureBASIC, par exemple avec OpenWindow() pour centrer une fenêtre et en même temps la mettre en plein écran. Ils permettent donc de spécifier certaines propriétés en n'utilisant qu'une seule variable.
Mais comment cela fonctionne-t-il ?
  • Un flag peut avoir pour valeur 0 ou 1.
  • Un entier long (.l) est codé sur 4 octets, soit 32 bits
Nous avons donc 32 bits que nous allons pouvoir mettre à 0 ou à 1, soit 32 flags.

Pour arriver à cela, il va cependant falloir respecter quelques règles.
  • La valeur de nos constantes doit être codée sur un seul bit des 32 bits.
  • Il faudra veiller à ne pas écraser la valeur de la variable, on ne pourra donc pas utiliser l'affectation =
1) Comment sont codés nos nombres ?
Nous pensons en base 2. On démarre du bit de poids faible 0 jusqu'au bit de poids fort 31. En décimal cela donne :

Code : Tout sélectionner

#Flag_0 = 1   ; = %1 en binaire (bit 0 fixé)
#Flag_1 = 2   ; = %10 (bit 1)
#Flag_2 = 4   ; = %100 (bit 2)
#Flag_3 = 8   ; = %1000 (bit 3)
#Flag_4 = 16  ; = %10000 (bit 4)
#Flag_5 = 32  ; = %100000 (bit 5)
#Flag_6 = 64  ; = %1000000 (bit 6) 
#Flag_7 = 128 ; = %10000000 (bit 7)
#Flag_8 = 256 ; = %100000000 (bit 8)
; Etc...
Un manière plus simple est de le faire en hexadécimal, $1, $2, $4, $8 par 4 octets

Code : Tout sélectionner

#Flag_0 = $0001 (bit 0 fixé)
#Flag_1 = $0002 (bit 1)
#Flag_2 = $0004 (bit 2)
#Flag_3 = $0008 (bit 3)
#Flag_4 = $0010 (bit 4)
#Flag_5 = $0020 (bit 5)
#Flag_6 = $0040 (bit 6)
#Flag_7 = $0080 (bit 7)
#Flag_8 = $0100 (bit 8)
; etc...
Ou en utilisant une énumération binaire

Code : Tout sélectionner

EnumerationBinary
    #Flags1 ; égale à 1
    #Flags2 ; égale à 2
    #Flags3 ; égale à 4
    #Flags4 ; égale à 8
    #Flags5 ; égale à 16
  EndEnumeration
2) Mettre une ou plusieurs valeurs, sans écraser les autres, par exemple pour passer vos flags à une fonction, se fait avec le OU logique (OR), opérateur "|" en PB.

Code : Tout sélectionner

mesFlags = #Flag_0 | #Flag_6 ;(= %01000001 en binaire ou $0041 en hexa ou 65 en décimal)
Le OU logique se comprend avec une table de vérité.
Exemple avec 2 valeurs :

Code : Tout sélectionner

A   B  SORTIE
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
Cet opérateur permet donc de ne modifier qu'un bit à la fois, sans altérer les autres.

3) Lire un flag, c'est à dire lire la valeur d'un bit spécifique.
Pour ce faire nous allons utiliser le ET logique (AND), opérateur "&" en PB. Voici sa table de vérité :

Code : Tout sélectionner

A   B  SORTIE
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1
La sortie n'est à 1 que si les deux entrées sont à 1.
Exemple :

Code : Tout sélectionner

mesFlags = #Flag_0 | #Flag_6
If mesFlags & #Flag_6
    Debug "Le bit 6 est à 1"
EndIf
If mesFlags & #Flag_3
    Debug "Le bit 3 est à 1"
Else
    Debug "Le bit 3 est à 0"
EndIf
Et si on veux maintenant modifié l'état d'un flags et le placer à 0, comment faire?

Pour cela nous allons utiliser l'opérateur AND (&) ainsi que l'opérateur NOT (~) comme ceci

Code : Tout sélectionner

mesFlags =mesFlags &~#Flags3
L'opérateur not va inversé tous les bits

Code : Tout sélectionner

0000 0000 0010 0000 ; #Flag5 (32 en décimal) 
1111 1111 1101 1111 ;devient après le NOT
Donc tous les bits à 1 seront simplement copiés avec l'opérateur ET le bit à 0 sera quant à lui mit à 0.

Exemple complet:

Code : Tout sélectionner

EnumerationBinary
    #Flags0 ; égale à 1
    #Flags1 ; égale à 2
    #Flags2 ; égale à 4
    #Flags3 ; égale à 8
     #Flags4 ; égale à 16
    #Flags5 ; égale à .32
    #Flags6 ;égale à 64
    #Flags7 ;égale à 128
EndEnumeration
Global mesFlags .l
Procedure Lit()
    For i=0 To 7
        p.l=Pow(2,i)
        If(mesFlags &p)
            Debug "Le flags "+Str(i)+" est à 1"
        Else
            Debug "Le flags "+Str(i)+" est à 0"
        EndIf
    Next
EndProcedure
; Ici j'active le Flag 1,3 et 5
mesFlags =#Flags1|#Flags3|#Flags5

; Lecture des flags pour voir le résultat
Lit()

; ici je vai placer le flag 3 à 0

mesFlags =mesFlags &~#Flags3

; Lecture des flags pour voir le résultat
Lit()

Voila, j'espère que ce petit tuto vous sera utile.

Merci à majikeyric et djes pour leurs remarques et corrections :wink:
Dernière modification par microdevweb le ven. 16/juin/2017 9:04, modifié 3 fois.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
majikeyric
Messages : 602
Inscription : dim. 08/déc./2013 23:19
Contact :

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par majikeyric »

... pauvre tache
Dernière modification par majikeyric le lun. 03/juil./2017 14:54, modifié 1 fois.
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par Zorro »

passé jusqu'à 32 flag
super_variable.s ="a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9,riri,fifi,loulou,et, autant,de,flag,que,tu,veux,dans,une,seule,variable,c'est ,étonnant,non,?"

54 flag dans ma super_variable ! ;) :mrgreen:

et ici : variable.i <<< 8 octets (avec compilateur 64-bit) -9223372036854775808 à +9223372036854775807 , ça en fait des flags ...


je veux dire, les flag c'est une petite memoire, qui permet de noter un evenement dans le prg ,qui resservira plus tard ...
a partir de là , pourquoi se bloquer sur du binaire ?

dans le cadre de la programmation sur Microprocesseur ...(assembleur ) ça peut s'envisager
mais en Purebasic .... franchement, je vois pas trop l’intérêt ...

Mais merci pour le tuto .. :)
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par microdevweb »

Merci majikeyric, pour l'astuce de l’énumération binaire;

Zorro, il m'arrive souvent dans mes procédures d'utiliser des flag et les fonctions de Purebasic aussi d’ailleurs maintenant libre à chaque personne d'en voir un intérêt ou pas :wink: .
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par Micoute »

Zorro a écrit :pourquoi se bloquer sur du binaire ?
Parce que c'est la seule langue que comprend le multiprocesseur et en plus on n'est absolument pas limité au binaire, les langages de haut niveau tel que PureBasic ont été créés pour ça

Merci microdevweb, j'apprécie ton tuto.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par djes »

Je t'ai corrigé tes fautes et aussi quelques erreurs. Il y a une faute aussi dans le titre, moi je mettrais plutôt "Utiliser les flags". Tu corriges si tu veux ;)

Code : Tout sélectionner

Bonjour à tous,

Les flags (drapeaux, en français) sont largement utilisés par les fonctions de PureBASIC, par exemple avec OpenWindow() pour centrer une fenêtre et en même temps la mettre en plein écran. Ils permettent donc de spécifier certaines propriétés en n'utilisant qu'une seule variable. 
Mais comment cela fonctionne-t-il ?
[list]
[*]Un flag peut avoir pour valeur 0 ou 1.
[*]Un entier long (.l) est codé sur 4 octets, soit 32 bits[/list]

Nous avons donc 32 bits que nous allons pouvoir mettre à 0 ou à 1, soit 32 flags.

Pour arriver à cela, il va cependant falloir respecter quelques règles.
[list]
[*] La valeur de nos constantes doit être codée sur un seul bit des 32 bits.
[*] Il faudra veiller à ne pas écraser la valeur de la variable, on ne pourra donc pas utiliser l'affectation =[/list]

1) Comment sont codés nos nombres ?
Nous pensons en base 2. On démarre du bit de poids faible 0 jusqu'au bit de poids fort 31. En décimal cela donne :
[code]
#Flag_0 = 1   ; = %1 en binaire (bit 0 fixé)
#Flag_1 = 2   ; = %10 (bit 1)
#Flag_2 = 4   ; = %100 (bit 2)
#Flag_3 = 8   ; = %1000 (bit 3)
#Flag_4 = 16  ; = %10000 (bit 4)
#Flag_5 = 32  ; = %100000 (bit 5)
#Flag_6 = 64  ; = %1000000 (bit 6) 
#Flag_7 = 128 ; = %10000000 (bit 7)
#Flag_8 = 256 ; = %100000000 (bit 8)
; Etc...
Un manière plus simple est de le faire en hexadécimal, $1, $2, $4, $8 par 4 octets

Code : Tout sélectionner

#Flag_0 = $0001 (bit 0 fixé)
#Flag_1 = $0002 (bit 1)
#Flag_2 = $0004 (bit 2)
#Flag_3 = $0008 (bit 3)
#Flag_4 = $0010 (bit 4)
#Flag_5 = $0020 (bit 5)
#Flag_6 = $0040 (bit 6)
#Flag_7 = $0080 (bit 7)
#Flag_8 = $0100 (bit 8)
; etc...
2) Mettre une ou plusieurs valeurs, sans écraser les autres, par exemple pour passer vos flags à une fonction, se fait avec le OU logique (OR), opérateur "|" en PB.

Code : Tout sélectionner

mesFlags = #Flag_0 | #Flag_6 ;(= %01000001 en binaire ou $0041 en hexa ou 65 en décimal)
Le OU logique se comprend avec une table de vérité.
Exemple avec 2 valeurs :

Code : Tout sélectionner

A   B  SORTIE
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
Cet opérateur permet donc de ne modifier qu'un bit à la fois, sans altérer les autres.

3) Lire un flag, c'est à dire lire la valeur d'un bit spécifique.
Pour ce faire nous allons utiliser le ET logique (AND), opérateur "&" en PB. Voici sa table de vérité :

Code : Tout sélectionner

A   B  SORTIE
0 | 0 -> 0
0 | 1 -> 0
1 | 0 -> 0
1 | 1 -> 1
La sortie n'est à 1 que si les deux entrées sont à 1.
Exemple :

Code : Tout sélectionner

mesFlags = #Flag_0 | #Flag_6
If mesFlags & #Flag_6
    Debug "Le bit 6 est à 1"
EndIf
If mesFlags & #Flag_3
    Debug "Le bit 3 est à 1"
Else
    Debug "Le bit 3 est à 0"
EndIf
Voila, j'espère que ce petit tuto vous sera utile.[/code]
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [TUTO] Utiliser les flags

Message par microdevweb »

Merci djes
c'est vrai que c'est un peux plus compréhensible
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Avatar de l’utilisateur
JohnJohnsonSHERMAN
Messages : 648
Inscription : dim. 13/déc./2015 11:05
Localisation : Allez, cherche...
Contact :

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par JohnJohnsonSHERMAN »

Merci pour ce tuto, bien que je connaissais déja le principe :) Ca a le mérite d'éclaircir certains points, en particulier pour récupérer un flag (je me rapelle jamais comment faire :mrgreen: ) :D

@Dobro : C'est plus dans la "philosophie" de PB de passer les flags avec des constantes numériques (genre "#PB_Window_ScreenCentered | #PB_Window_SystemMenu"), plutôt que de le faire avec une chaine ou autres, et la méthode binaire est tout simplement la mieux adaptée à des flags numériques combinables ;) En plus ca fait "propre" je trouve.
"Le bug se situe entre la chaise et le clavier"
Votre expert national en bogage et segfaults.

CPU : AMD A8 Quad core - RAM 8Gb - HDD 2To
  • Windows 10 x64 - PB 5.61 x64
  • Linux Ubuntu 16.04 LTS x64 (dual boot) - PB pas encore réinstallé
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: [TUTO] Utiliser les flags

Message par djes »

microdevweb a écrit :Merci djes
c'est vrai que c'est un peux plus compréhensible
De rien, le plus dur, c'est de commencer lorsqu'on se retrouve devant une "feuille blanche". Merci à toi !
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: [TUTO] passé jusqu'à 32 flag avec une seule variable

Message par Zorro »

JohnJohnsonSHERMAN a écrit : @Dobro : C'est plus dans la "philosophie" de PB de passer les flags avec des constantes numériques (genre "#PB_Window_ScreenCentered | #PB_Window_SystemMenu"), plutôt que de le faire avec une chaine ou autres, et la méthode binaire est tout simplement la mieux adaptée à des flags numériques combinables ;) En plus ca fait "propre" je trouve.

je ne critique pas l'optimisation de la chose :)
je dis juste que le binaire n'est pas obligatoire

la tu parles toi même de "passage de Flags" ...
en fait il s'agit de parametres , hors ce système permet de diminuer le nombre de parametres ....
mais est limité par l'information (0 ou 1 )
hors un flag peut véhiculer des informations bien plus complexes que 0 ou 1

c'est juste ça que je souligne , et que le Tuto n'aborde pas

prenons un exemple alors ...

Code : Tout sélectionner


Procedure test(Fl.s)
		If stringfield(FL,1,",")="a"
				debug "Fl=a"
		Endif
		;
		If stringfield(FL.s,2,",")="b"
				debug "Fl=b"
		Endif
		If stringfield(FL.s,3,",")="f" ; <<< ne trouvera pas cette valeur qui pourrai allez de a à z , ou l'infini si on utilise des mots et plus de lettres
				debug "Fl=f"
		Else
				debug "pas activé le 3em parametre" ; <<< no limite !!
		Endif
		If stringfield(FL.s,4,",")="super parametre"
				debug "Fl=super parametre"
		Endif
EndProcedure
calldebugger
Flagg.s="a,b,c,super parametre"
test(Flagg.s)


on perd probablement en vitesse , mais on gagne en richesse d'informations (ce qui au final, peut nous avoir fait gagner de la vitesse ) :)
Dernière modification par Zorro le ven. 23/déc./2016 20:40, modifié 1 fois.
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: [TUTO] Utiliser les flags

Message par Kwai chang caine »

Pour une fois, comme notre "cher man", je connaissais aussi le principe, j'en avais eu besoin dans un de mes codes et SHARDIK, de mémoire, m'avait dépanné 8)
Ce TUTO est génial car tu expliques en détail ce phénomène que je trouve vraiment MAGIQUE 8O
Merci 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [TUTO] Utiliser les flags

Message par microdevweb »

J'ai ajouté au tuto la manière de procéder pour placer une flags spécifique à 0.

Bonne fête à tous :wink:
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
boddhi
Messages : 573
Inscription : lun. 26/avr./2010 16:14
Localisation : N 48° 1' 33.6" / E 0° 36' 11.3"

Re: [TUTO] Utiliser les flags

Message par boddhi »

Bonjour,

A la lecture de ce tutoriel, je me permets juste de signaler une petite coquille au point 3 du tuto :
3) Lire un flag, c'est à dire lire la valeur d'un bit spécifique.
Pour ce faire nous allons utiliser le ET logique (AND), opérateur "&" en PB. Voici sa table de vérité :

Code : Tout sélectionner

A   B  SORTIE
0 | 0 -> 0
0 | 1 -> 0
1 | 0 -> 0
1 | 1 -> 1
où il faudrait lire :

Code : Tout sélectionner

A   B  SORTIE
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1

Cordialement.
Avatar de l’utilisateur
Zorro
Messages : 2185
Inscription : mar. 31/mai/2016 9:06

Re: [TUTO] Utiliser les flags

Message par Zorro »

exacte !! :)
Image
Image
Site: http://michel.dobro.free.fr/
Devise :"dis moi ce dont tu as besoin, je t'expliquerai comment t'en passer"
Avatar de l’utilisateur
microdevweb
Messages : 1798
Inscription : mer. 29/juin/2011 14:11
Localisation : Belgique

Re: [TUTO] Utiliser les flags

Message par microdevweb »

@boddhi,

C'est corrigé, merci pour cette remarque pertinente.
Windows 10 64 bits PB: 5.70 ; 5.72 LST
Work at Centre Spatial de Liège
Répondre