positionner un bit sur un int

positionner un bit sur un int - C - Programmation

Marsh Posté le 16-11-2005 à 21:48:22    

bonjour,
 
J'ai un int qui représente un tableau de 32 bits.
Si il y'a un 0 au bit 0 ca veut dire que la premiere case est vide
et un 1 si elle est pleine.
 
Je cherche une opération pour positionner le ième bit de mon int à 1
genre : set_bit(int mon_int, int position) => met a 1
            rem_bit(int mon_int, int position) => met a 0
 
j'ai trouvé ca sur le site koders

Code :
  1. #define SET_BIT(flag,bit) ((flag) |= (bit))
  2. #define REMOVE_BIT(flag,bit) ((flag) &= ~(bit))


mais je ne sais pas comment l'utiliser ...
si je fais dans mon code  mon_int = SET_BIT(mon_int, position_a_changer);
c'est censé marcher ??
 
 
je vous remercie ...
 

Reply

Marsh Posté le 16-11-2005 à 21:48:22   

Reply

Marsh Posté le 16-11-2005 à 21:59:06    

meumeul a écrit :

bonjour,
 
J'ai un int qui représente un tableau de 32 bits.
Si il y'a un 0 au bit 0 ca veut dire que la premiere case est vide
et un 1 si elle est pleine.
 
Je cherche une opération pour positionner le ième bit de mon int à 1
genre : set_bit(int mon_int, int position) => met a 1
            rem_bit(int mon_int, int position) => met a 0
 
j'ai trouvé ca sur le site koders

Code :
  1. #define SET_BIT(flag,bit) ((flag) |= (bit))
  2. #define REMOVE_BIT(flag,bit) ((flag) &= ~(bit))


mais je ne sais pas comment l'utiliser ...
si je fais dans mon code  mon_int = SET_BIT(mon_int, position_a_changer);
c'est censé marcher ??


Ceci est-il plus clair ?
 
http://mapage.noos.fr/emdel/clib/ed/inc/bits.h
 
Sinon, tu peux aussi recoder ta propre macro, c'est plus pédagogique...
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 16-11-2005 à 22:04:03    

Emmanuel Delahaye a écrit :

Ceci est-il plus clair ?
 
http://mapage.noos.fr/emdel/clib/ed/inc/bits.h
 
Sinon, tu peux aussi recoder ta propre macro, c'est plus pédagogique...


 
voila ce qui m'interesse dans ton .h
 
/* mask set/clear/toggle */
#define mSET(d_, m_) ((d_) |=  (m_))
#define mCLR(d_, m_) ((d_) &= ~(m_))
 
Il semblerait que ca soit la meme chose que j'ai trouvé. L' utilisation que j'ai décrite plus haut
est elle correcte ? j'ai du mal a la faire marcher en fait ...

Reply

Marsh Posté le 16-11-2005 à 22:21:11    

Sinon j'ai un autre idée :  
 

Code :
  1. int set_bit(int val, int pos) {
  2.      if (val < pow(2,pos)
  3.          val += pow(2,pos);
  4.     return val;
  5. }


 
Qu'en pensez vous ?

Message cité 1 fois
Message édité par meumeul le 16-11-2005 à 22:23:05
Reply

Marsh Posté le 16-11-2005 à 22:22:36    

meumeul a écrit :

voila ce qui m'interesse dans ton .h
 
/* mask set/clear/toggle */
#define mSET(d_, m_) ((d_) |=  (m_))
#define mCLR(d_, m_) ((d_) &= ~(m_))
 
Il semblerait que ca soit la meme chose que j'ai trouvé. L' utilisation que j'ai décrite plus haut
est elle correcte ? j'ai du mal a la faire marcher en fait ...


d_, c'est la donnée (data)
m_, c'est le masque (mask)
 
La relation entre le masque et le numéro de bit est donné par la macro BIT()
 
Mettre le bit 3 de x à 1  

unsigned x = 0;
 
mSET (x, BIT(3));

ou, puisque les définitions existent...

mSET (x, bit3);


Message édité par Emmanuel Delahaye le 16-11-2005 à 22:24:41

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 16-11-2005 à 22:23:55    

meumeul a écrit :

Sinon j'ai un autre idée :  
 

Code :
  1. int set_bit(int val, int pos) {
  2.      if (val < pow(2,pos)
  3.          val += pow(2,pos);
  4. }


 
Qu'en pensez vous ?


Horrible !
 
En fait horriblement lent... Les bitwise operators sont là pour ça.
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 16-11-2005 à 22:28:37    

Emmanuel Delahaye a écrit :

Horrible !
 
En fait horriblement lent... Les bitwise operators sont là pour ça.


 
en plus j'ai inversé les params de mes appels a pow(...,...)

Reply

Marsh Posté le 17-11-2005 à 01:10:13    

Code :
  1. #define SET_BIT(_lval, _bit) ((_lval) |= (1<<(_bit)))


Ou un truc dans le genre. Je te laisse faire l'autre macro.

Reply

Marsh Posté le 17-11-2005 à 11:13:42    

meumeul a écrit :

j'ai trouvé ca sur le site koders

Code :
  1. #define SET_BIT(flag,bit) ((flag) |= (bit))
  2. #define REMOVE_BIT(flag,bit) ((flag) &= ~(bit))


mais je ne sais pas comment l'utiliser ...


 
Les opérateurs "&", "|" , "^" et "~" permettent de faire un "ET", un "OU", un "NOT" et un "XOR" sur une ou deux valeurs... mais "bit à bit"
 
Exemple:
val1 = 10 (1010 binaire)
val2 = 12 (1100 binaire)
 
val1 | val2 = 1110 binaire soit 14
val1 & val2 = 1000 binaire soit 8
val1 ^ val2 = 0110 binaire soit 6
~val1 = 0101 binaire soit 5
~val2 = 0011 binaire soit 3
 
Partant de là, tu peux combiner ces opérateurs à souhait pour mettre le bit que tu veux à 1, à 0, vérifier s'il est à 1 ou pas
Exemple
#define BIT1     (0x01)
#define BIT2     (0x02)
#define BIT3     (0x04)
#define BIT4     (0x08)
#define BIT5     (0x10)
#define BIT6     (0x20)
#define BIT7     (0x40)
#define BIT8     (0x80)
 
int flag=0;
 
Je veux mettre le 4° bit du flag (en partant de la droite) à 1 => flag=flag | BIT4
Je veux mettre le 5° bit du flag à 0 => flag=flag & (~BIT5)
Je veux permuter le 6° bit du flag => flag=flag ^ BIT6
Je veux vérifier si le 7° bit du flag vaut 1 => "if (flag & BIT7)" ou bien "if ((flag & BIT7) == BIT7)"
 
Une fois que t'as compris le principe, t'as plus qu'à écrire des macro plus parlantes telles que "FLAG_ON", "FLAG_OFF" etc...

Message cité 1 fois
Message édité par Sve@r le 17-11-2005 à 11:18:05

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 17-11-2005 à 18:46:32    

Sve@r a écrit :

Les opérateurs "&", "|" , "^" et "~" permettent de faire un "ET", un "OU", un "NOT" et un "XOR" sur une ou deux valeurs... mais "bit à bit"
 
Exemple:
val1 = 10 (1010 binaire)
val2 = 12 (1100 binaire)
 
val1 | val2 = 1110 binaire soit 14
val1 & val2 = 1000 binaire soit 8
val1 ^ val2 = 0110 binaire soit 6
~val1 = 0101 binaire soit 5
~val2 = 0011 binaire soit 3
 
Partant de là, tu peux combiner ces opérateurs à souhait pour mettre le bit que tu veux à 1, à 0, vérifier s'il est à 1 ou pas
Exemple
#define BIT1     (0x01)
#define BIT2     (0x02)
#define BIT3     (0x04)
#define BIT4     (0x08)
#define BIT5     (0x10)
#define BIT6     (0x20)
#define BIT7     (0x40)
#define BIT8     (0x80)
 
int flag=0;
 
Je veux mettre le 4° bit du flag (en partant de la droite) à 1 => flag=flag | BIT4
Je veux mettre le 5° bit du flag à 0 => flag=flag & (~BIT5)
Je veux permuter le 6° bit du flag => flag=flag ^ BIT6
Je veux vérifier si le 7° bit du flag vaut 1 => "if (flag & BIT7)" ou bien "if ((flag & BIT7) == BIT7)"
 
Une fois que t'as compris le principe, t'as plus qu'à écrire des macro plus parlantes telles que "FLAG_ON", "FLAG_OFF" etc...


 
 
 
super, merci a tous pour votre aide.
Tant qu'on est dans les histoires de bits, j'ai un autre probleme que je ne saisi pas :

Code :
  1. long int ttt = (long int) pow(2,30);
  2.       printf("test %d\n", ttt);


Le code marche et affiche la bonne valeur.
mais

Code :
  1. long int ttt = (long int) pow(2,31);
  2.       printf("test %d\n", ttt);


retourne un nombre negatif...
 
Je pensais que ca n'étais le cas que pour  pow(2,32) !
Alors je me suis dit que le bit de poids fort était reservé pour le signe.
Donc j'ai déclaré mes "long int" en "unsigned long int"
mais pow(2,31) est toujours négatif ....
 
Et j'ai vraiment besoin quil soit positif. Je ne vois pas pourquoi il ne l'est pas :S
 
Une idée ?? Merci ...

Reply

Marsh Posté le 17-11-2005 à 18:46:32   

Reply

Marsh Posté le 17-11-2005 à 18:54:26    

meumeul a écrit :

Et j'ai vraiment besoin quil soit positif. Je ne vois pas pourquoi il ne l'est pas


Dans ce cas, utiliser des non signés et le bon formatteur.


   unsigned long ttt = pow(2,31);
   printf("test %lu\n", ttt);


Message édité par Emmanuel Delahaye le 17-11-2005 à 18:56:54

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 17-11-2005 à 18:57:10    

Génial ...  J'ai un peu honte :( mais je débute encore en C.
Il était bien nécessaire de le mettre unsigned alors ...
 
Merci !

Reply

Marsh Posté le 17-11-2005 à 20:51:51    

Juste un truc, suite à l'une de tes remarques : il faut faire très attention si tu comptes utiliser des nombres de l'ordre de grandeur de la valeur max autorisée par un type, parce que le C ne te prévient pas s'il dépasse la capacité du type. Tu peux très bien avoir un résultat complètement faux sans que tu ne t'en rendes compte, ou alors trop tard. Donc il faut absolument s'assurer que les manips/calculs n'engendreront pas de dépassement, et là, il n'y a pas d'autre technique pour éviter le bug que de bien vérifier les ordres de grandeur utilisés dans les calculs.


---------------
Les aéroports où il fait bon attendre, voila un topic qu'il est bien
Reply

Marsh Posté le 18-11-2005 à 10:03:06    

meumeul a écrit :

Génial ...  J'ai un peu honte :( mais je débute encore en C.
Il était bien nécessaire de le mettre unsigned alors ...
 
Merci !


Il y a le problème de la déclaration du type qui te permet de faire des calculs corrects... et celui du format d'affichage de "printf" qui demande à "printf" de considérer la valeur comme signée ou pas.
 
Exemple:
short a=0x8000       => a vaut     1000 0000 0000 0000
long b=a                 => b vaudra 1111 1111 1111 1111 1000 0000 0000 0000
Etant donné que tu travailles en "signé", et que le bit de signe vaut "1", celui-ci est étendu sur le long pour que la valeur soit la même entre "a" et "b"
 
Maintenant
unsigned short a=0x8000       => a vaut 1000 0000 0000 0000
long b=a                             => b vaudra 0000 0000 0000 0000 1000 0000 0000 0000
Comme "a" est non signé, le "1" ne signifie plus "nombre négatif" mais "valeur" et n'a pas à être étendu sur le "long"
 
Maitenant, quand tu affiches "a" ou "b" avec "printf", c'est à toi de spécifier si la valeur que tu lui passes doit être considérée comme signée ou pas... parce que "printf" ne connait pas le type de "a" ou "b" d'où le :
- %u pour un int qu'on veut afficher en non signé
- %d pour un int qu'on veut afficher en signé
- %hu pour un short qu'on veut afficher en non signé
- %hd pour un short qu'on veut afficher en signé
- %lu pour un long qu'on veut afficher en non signé
- %ld pour un long qu'on veut afficher en signé
 
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 18-11-2005 à 18:00:59    

meumeul a écrit :

Génial ...  J'ai un peu honte :( mais je débute encore en C.
Il était bien nécessaire de le mettre unsigned alors ...
 
Merci !


C'est pas lié au C c'est de la logique combinatoire. Il ne faut pas tout confondre.

Reply

Marsh Posté le 21-11-2005 à 12:31:15    

Bonjour
soit le programme suivant :
 
#include <stdio.h>
 
int main (int argc, char *argv[])
{
        short           a;
        unsigned short  b;
        long            c;
        long            d;
 
        a = 0x8000;
        b = 0x8000;
        c = a;
        d = b;
        printf ("short : %x, long : %x\n", a, c);
        printf ("unsigned short : %x, long : %x\n", b, d);
}
 
"sanssigne.c" [Nouveau] 21L, 375C écrit(s)
fronsac:13> gcc -o sanssigne sanssigne.c
fronsac:14> sanssigne
short : ffff8000, long : ffff8000
unsigned short : 8000, long : 8000
 
Au vu du résultat produit, il semblerait que gcc décide de coder les short sur 32 bits.
Si un spécialiste de la norme pouvait éclairer ce comportement, nous en serions ravi !

Reply

Marsh Posté le 21-11-2005 à 12:54:07    

db__ a écrit :

Bonjour
soit le programme suivant :

fronsac:14> sanssigne
short : ffff8000, long : ffff8000
unsigned short : 8000, long : 8000


Au vu du résultat produit, il semblerait que gcc décide de coder les short sur 32 bits.
Si un spécialiste de la norme pouvait éclairer ce comportement, nous en serions ravi !


 
Comment le sais tu ? Tu passes un short à une fonction variadic. Il est converti en int. Comme il est signé, le signe est étendu parce que ton implémentation utilisé la représentation 'complément à deux' pour les nombres négatifs.
 
de plus, tu utilises le formatteur "%" qui attentd un int non signé. Le résultat est donc indéterminé... Mon compilateur m'a prévenu :  


../main.c: In function `main_':
../main.c:15: warning: unsigned int format, long int arg (arg 3)
../main.c:16: warning: unsigned int format, long int arg (arg 3)


Ce code est maintenant conforme à la norme


#include <stdio.h>
 
int main (void)
{
   short a;
   unsigned short b;
   long c;
   long d;
 
   a = 0x8000;
   b = 0x8000;
   c = a;
   d = b;
   printf ("short : %hx, long : %lx\n", (unsigned short) a, c);
   printf ("unsigned short : %hx, long : %lx\n", (unsigned short) b, d);
 
   return 0;
}


et le résultat est conforme aux attentes.


short : 8000, long : ffff8000
unsigned short : 8000, long : 8000

Message cité 1 fois
Message édité par Emmanuel Delahaye le 21-11-2005 à 15:43:01

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 21-11-2005 à 15:07:59    

Emmanuel Delahaye a écrit :

Comment le sais tu ? Tu passes un short à une fonction variadic. Il est converti en int. Comme il est signé, le signé est étendu parce que ton implémentation utilisé la représentation 'complément à deux' pour les nombres négatifs.
 
de plus, tu utilises le formatteur "%" qui attentd un int non signé. Le résultat est donc indéterminé...


 
Héhé... tout le problème de l'indépendance qu'il y a entre "type" et "affichage"...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 22-11-2005 à 12:29:21    

J'ai vérifié par une sortie assembleur de la compilation qu'il code effectivement bien les short en 16 bits mais qu'il envoie sur la pile uniquement des 32 bits avec ou pas extension de signe suivant le cas. printf ne prend donc que des arguments de 32 bits.
Je savais qu'il y avait indépendance entre variable et affichage mais je n'imaginais pas qu'il y ait changement de taille de variable  pour la représenter.
merci pour ces informations.

Reply

Marsh Posté le 22-11-2005 à 13:17:15    

db__ a écrit :

J'ai vérifié par une sortie assembleur de la compilation <...>


Chaque implémentation fait ce qu'elle veux. L'implémentation n'est pas définie par le langage. Ce que définit le langage ce sont les comportements et les interfaces.
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 22-11-2005 à 18:45:39    

pour quelque chose de portable est ce qu'il existe une structure byte qui a 1 octet d'info exactement.

Reply

Marsh Posté le 22-11-2005 à 18:53:46    

lol :-)

Reply

Marsh Posté le 22-11-2005 à 19:22:18    

minimoke a écrit :

pour quelque chose de portable est ce qu'il existe une structure byte qui a 1 octet d'info exactement.


Un unsigned char. fait par définition exactement un byte.
 
Par contre, la notion de "exactement un octet" n'existe pas en C de façon portable. Un char fait au moins 8 bits. Il peut en faire plus.
 
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 28-11-2005 à 14:00:18    

ok merci , tant quon est dans les bits, j'ai une petite derniere question.
Je prends ces unsigned long int pour représenter des ensembles de 1 à 32 inclus en fait.  
Pour les opération ensemblistes de base tel que l'union l'intersection et le complément, pas de problème, j'utilise | & et ~ .  
Mais pour la 'différence' de deux ensembles, je trouve pas d'autres moyen que de regarder chacun des 32 bits deux a deux des deux opérandes de la différence. Y'a t il un moyen avec une combinaison d'opérateurs bits a bits ? Je vois pas du tout ... j'ai tenté des trucs avec un complément de l'intersection mais c'est pas du tout ca lol

Reply

Marsh Posté le 28-11-2005 à 14:16:00    

^ (ou exclusif) ?
dans le résultat les bits ne correspondant pas seront à 1, ceux correspondant à 0


---------------
-( BlackGoddess )-
Reply

Marsh Posté le 28-11-2005 à 14:18:44    

on  m'a proposé ca ailleurs :  
a - b = a & (~ b)
 
je vais le tester

Reply

Marsh Posté le 28-11-2005 à 14:22:18    

le ^ marche pas : (la condition n'est pas suffisante)
 
{1,2} diff {1,4} donne { 2 , 4 } au lieu de {2}
 

Reply

Marsh Posté le 28-11-2005 à 16:23:09    

meumeul a écrit :

on  m'a proposé ca ailleurs :  
a - b = a & (~ b)


Ça marche.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed