positionner un bit sur un int - C - Programmation
Marsh Posté le 16-11-2005 à 21:59:06
meumeul a écrit : bonjour,
|
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...
Marsh Posté le 16-11-2005 à 22:04:03
Emmanuel Delahaye a écrit : Ceci est-il plus clair ? |
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 ...
Marsh Posté le 16-11-2005 à 22:21:11
Sinon j'ai un autre idée :
Code :
|
Qu'en pensez vous ?
Marsh Posté le 16-11-2005 à 22:22:36
meumeul a écrit : voila ce qui m'interesse dans ton .h |
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; |
ou, puisque les définitions existent...
mSET (x, bit3); |
Marsh Posté le 16-11-2005 à 22:23:55
meumeul a écrit : Sinon j'ai un autre idée :
|
Horrible !
En fait horriblement lent... Les bitwise operators sont là pour ça.
Marsh Posté le 16-11-2005 à 22:28:37
Emmanuel Delahaye a écrit : Horrible ! |
en plus j'ai inversé les params de mes appels a pow(...,...)
Marsh Posté le 17-11-2005 à 01:10:13
Code :
|
Ou un truc dans le genre. Je te laisse faire l'autre macro.
Marsh Posté le 17-11-2005 à 11:13:42
meumeul a écrit : j'ai trouvé ca sur le site koders
|
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...
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" |
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 :
|
Le code marche et affiche la bonne valeur.
mais
Code :
|
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 ...
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.
|
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 !
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.
Marsh Posté le 18-11-2005 à 10:03:06
meumeul a écrit : Génial ... J'ai un peu honte |
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é
Marsh Posté le 18-11-2005 à 18:00:59
meumeul a écrit : Génial ... J'ai un peu honte |
C'est pas lié au C c'est de la logique combinatoire. Il ne faut pas tout confondre.
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 !
Marsh Posté le 21-11-2005 à 12:54:07
db__ a écrit : Bonjour
|
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 :
|
Ce code est maintenant conforme à la norme
|
et le résultat est conforme aux attentes.
|
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. |
Héhé... tout le problème de l'indépendance qu'il y a entre "type" et "affichage"...
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.
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.
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.
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.
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
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
Marsh Posté le 28-11-2005 à 14:18:44
ReplyMarsh 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}
Marsh Posté le 28-11-2005 à 16:23:09
Reply
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
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 ...