affichage bit par bit - C - Programmation
Marsh Posté le 09-07-2010 à 20:03:29
Code :
|
Marsh Posté le 11-07-2010 à 23:51:08
Sve@r a écrit :
|
salut,
merci pour vos réponses, c'est juste une question qui me passait par la tête car je n'ai pas l'habitude d'utiliser les opérateurs de bit.
Quand on parle de "trois binaire" par exemple, ça veut juste dire que c'est un trois sous forme d' "int" non ?
Sve@r, est ce que tu peux expliciter ce que veux dire "0x01" ? Pourquoi est ce que 1 doit être écrit en hexa ?
Si j'ai bien compris, tu fais un masquage en décalant le 1, soit par exemple pour 9 = 00000000 ... 1001 (sur 32 bits) :
0000000000 ... 1001 & 0000000 ...... 00001
0000000000 ... 1001 & 0000000 ...... 00010
0000000000 ... 1001 & 0000000 ...... 00100
.
.
.
0000000000 ... 1001 & 1000000 ...... 00000
c'est ça ?
merci par avance
Marsh Posté le 12-07-2010 à 08:54:12
in_your_phion a écrit : Quand on parle de "trois binaire" par exemple, ça veut juste dire que c'est un trois sous forme d' "int" non ? |
3 en binaire c'est 11
in_your_phion a écrit : Sve@r, est ce que tu peux expliciter ce que veux dire "0x01" ? Pourquoi est ce que 1 doit être écrit en hexa ? |
Rien n'est obligatoire en matière d'écriture. C'est juste une convention. Quand on utilise des flags booléens, on peut les écrire
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024
ou bien
0x001, 0x002, 0x004, 0x008, 0x010, 0x020, 0x040, 0x080, 0x100, ...
Avec la seconde écriture, on perçoit (à mon sens) mieux la logique de la série. De plus, la conversion hexa->binaire se fait de tête (chaque digit du chiffre hexa est écrit en binaire sur 4 digits) alors que la conversion décimal->binaire nécessite un calcul (division puis récupération des restes)
in_your_phion a écrit : Si j'ai bien compris, tu fais un masquage en décalant le 1, soit par exemple pour 9 = 00000000 ... 1001 (sur 32 bits) : |
Exact
Marsh Posté le 12-07-2010 à 22:28:30
merci!
Sve@r a écrit :
|
en fait, je pensais à un message qu'on code ou qu'on décode pour envoyer à un autre programme. Souvent, on voit le message avec des balises du style "3 binaire à la fin" (ce qui correspond à STX/ETX en ASCII je crois). Dans ce cas, ça veut dire qu'on code/décode tout le message en ASCII en regardant si à la fin il y a la balise ETX ?
par exemple, pour un message du type <STX>xxxxxxxx<ETX> (ou xxx c'est les données) je décode en ASCII ?
Marsh Posté le 13-07-2010 à 12:30:04
l'ascii, c'est une table de caractère. Ce n'est donc qu'un autre choix de représentation de tes valeurs. Si tu dois lire un octet qui a la valeur 3, que ce soit du binaire, que ce soit de l'hexa, que ce soit du décimal, que ce soit le caractère ascii 3, ca revient au même. Par contre, évidemment, le 3ème caractère de la table ascii n'est pas le caractère '3'.
Bref, dans ton cas, si c'est un délimiteur pour t'annoncer des débuts ou fins de blocs sémantiques dans tes données binaires, j'ai envie de te dire de ne pas te soucier de questions d'ascii, considère que c'est un 3.
Marsh Posté le 18-07-2010 à 11:26:31
theshockwave a écrit : l'ascii, c'est une table de caractère. Ce n'est donc qu'un autre choix de représentation de tes valeurs. Si tu dois lire un octet qui a la valeur 3, que ce soit du binaire, que ce soit de l'hexa, que ce soit du décimal, que ce soit le caractère ascii 3, ca revient au même. Par contre, évidemment, le 3ème caractère de la table ascii n'est pas le caractère '3'. Bref, dans ton cas, si c'est un délimiteur pour t'annoncer des débuts ou fins de blocs sémantiques dans tes données binaires, j'ai envie de te dire de ne pas te soucier de questions d'ascii, considère que c'est un 3. |
hello
ok, merci pour tes explications! J'aurais encore une autre question si possible C'est un peu du C++ car c'est avec une classe à l'origine, mais bon ce serait exactement pareil avec une structure en C donc je vais expliquer avec ça : si j'ai une structure avec des champs / valeurs, par exemple :
Code :
|
Dans mon programme, je créer des objets avec cette structure :
Code :
|
ou encore je créer d'autres objets avec plus ou moins de champs, ils devront êtres encodés avant d'être envoyés, non ?
Comment je peux encoder cette structure ? Il faudrait que je fasse une boucle sur les champs de la structure ? c'est possible ?
En fait, je crois que c'est lié à la serialization en binaire, mais je sais pas trop comment faire, c'est compliqué ?
Marsh Posté le 18-07-2010 à 17:57:18
in_your_phion a écrit : si j'ai une structure avec des champs / valeurs, par exemple :
|
A toi de voir. Rien ne t'oblige à remplir les champs. Dans le cas où tu t'abstiens, ils auront quand-même une valeur définie par l'état de la mémoire à ce moment là...
in_your_phion a écrit : Comment je peux encoder cette structure ? Il faudrait que je fasse une boucle sur les champs de la structure ? c'est possible ? |
Non. On peut pas boucler sur les champs. Surtout que l'optimiseur peut rajouter des bits intermédiaires pour caler la taille de la structure sur une puissance de 2 (plus rapide si on gère par la suite des tableaux de structures)
Mais rien ne t'empêche d'utiliser la notation "initialisation"
Code :
|
Marsh Posté le 18-07-2010 à 23:03:30
hello,
ok merci! je vais essayer ta méthode je pense, mais j'ai un formalisme objet alors ce sera peut être un peu plus compliqué
Juste pour être sûr, quand j'écris dans le buffer de sortie (qui va être envoyé à l'autre application - cliente ou serveur), ce serait comme ça ?
Code :
|
Marsh Posté le 21-07-2010 à 22:41:50
in_your_phion a écrit : hello,
|
Au lieu de faire pbuf+=4, fais donc pbuf+=sizeof(le truc précédent qui y a été stocké). Ce sera un poil plus portable.
Sinon en ce qui concerne ta "sérialisation", la méthode est correcte. Mais tu ne pourras récupérer ton objet de l'autre coté que si tu te trouves sur la même architecture, avec le même compilo, le même processeur, etc. Parce que chaque architecture a sa propre façon de gérer les nombres et les structures. Dommage que Emmanuel ne soit pas là, il a déjà écrit des trucs à ce sujet...
Marsh Posté le 21-07-2010 à 23:22:43
salut,
merci pour ta réponse!
donc par exemple il faudrait faire :
Code :
|
?
Sve@r a écrit :
|
ça a un rapport avec le codage little endian/big endian ? et si j'envoie juste ce buffer de char, ça sera toujours un buffer de char de l'autre côté non ? (Avec un décodage pê différent mais ce ne sera pas à moi de le gérer)
Marsh Posté le 22-07-2010 à 14:18:48
in_your_phion a écrit : |
par convention, l'endianness sur les réseaux est en big endian. Si tu fais ta petite tambouille dans ton coin et que ton appli tourne sur deux machines à toi qui fonctionnent sur la même architecture, ca ne te posera pas de souci de ne pas respecter cette convention. Par contre, si tu dois communiquer avec de vrais clients, ca risque des les agacer de recevoir des données qui sont juste des tableaux de caractères qui représentent des entier dans ton endianness à toi.
Qui plus est, effectivement, le padding de tes structures est à prendre en compte. Je ne peux qu'appuyer le conseil qu'on t'a fait précédemment, à savoir : utiliser sizeof.
Marsh Posté le 22-07-2010 à 18:53:27
in_your_phion a écrit : salut,
|
Code :
|
in_your_phion a écrit : et si j'envoie juste ce buffer de char, ça sera toujours un buffer de char de l'autre côté non ? |
Oui mais non. Si tu descends tes nombres en octets, ils seront écrits dans l'ordre que ta machine utilise. Si de l'autre coté la machine les code dans l'autre sens...
Exemple: le nombre 500 est codé 1F04 en binaire (ici hexa mais c'est pareil). Tu envoies donc 1F puis 04. De l'autre coté, il reçoit 1F puis 04 comme il faut. Manque de bol, lui il code dans l'autre sens. Donc chez-lui, ce 1F04 sera décodé en 95.
in_your_phion a écrit : (Avec un décodage pê différent mais ce ne sera pas à moi de le gérer) |
Ouais t'as raison. T'as qu'à benner tes octets en vrac et le bonobo d'en face n'aura qu'à se dém... pour remettre tout ça dans l'ordre. Tant qu'à faire, tu conclues ton envoie par "ce puzzle 5000 pièces vous a été offert par "
in_your_phion a écrit :
|
theshockwave a bien résumé le truc. Et malgré ça, même utiliser sizeof ne règle pas tous les problèmes. Parce que si la structure est codée d'une certaine façon sur l'ordi de départ (par exemple le padding est au tout début) et que sur l'ordi d'arrivée elle est codée différemment (avec par exemple padding à la fin), ben flipflap la girafe quoi.
La méthode préconisée pour sérializer une structure sur un réseau est de sérializer chacun de ses éléments. Et si certains éléments sont des int ou des long, alors il faut les convertir en entier "réseau" avant de les envoyer en utilisant les fonctions htons (host to net short) ou htonl (host to net long) selon le nombre. Et de l'autre coté, on récupère les nombres en utilisant ntohs (net to host short) ou ntohl (net to host long).
Marsh Posté le 22-07-2010 à 19:37:07
theshockwave a écrit : à noter d'ailleurs que l'endianness des floats est incertaine ... |
Je m'étais amusé une fois à coder des fonctions qui jouaient le rôle de htonf, htond, ntohf et ntohd pour gérer le problème des float et des double
Code :
|
Je ne sais pas ce qu'elles valent en grandeur nature... mais elles fonctionnaient pour envoyer et recevoir des float et des double entre un Unix et un Windows
Marsh Posté le 23-07-2010 à 10:40:59
ce que je voulais dire, c'est qu'il n'y a pas de convention little endian ou big endian pour les floats sur le réseau, donc tu peux les traiter ou non, ca n'a pas d'importance (et d'ailleurs, ce n'est pas parce qu'un processeur est en little endian que les floats sont nécessairement traités en little endian aussi)
Du coup, il n'y a pas de htonf qui tienne vraiment la route
Marsh Posté le 06-10-2011 à 14:11:22
theshockwave a écrit : |
Up, salut en fait j'aurais une question relative à ce sujet, par rapport à ce que tu me dis
Si ma machine/proc est en little endian et que je veux envoyer des données sur le reseau, je dois faire une conversion en Big Endian avant, c'est ça ? Ou est ce que c'est le réseau qui le fait pour moi ?
Par ailleurs si je suis sur une machine little endian, est ce que je dois forcément décoder les donnés codées sur plusieurs octets et les remettre en Little endian ?
Merci par avance
Marsh Posté le 06-10-2011 à 21:51:07
Bigre, 14 mois plus tard... Heureusement que je suis averti par email sinon serais jamais revenu voir...
in_your_phion a écrit : salut en fait j'aurais une question relative à ce sujet, par rapport à ce que tu me dis |
Le réseau ne fait aucune conversion. Il transmet ce qu'on lui donne et point barre.
1) Tu dois convertir ton nombre en nombre "réseau" via une primitive "htons()" (Host to Net Short) ou "htonl()" (Host to Net Long) selon le nombre d'origine (short ou long)
2) tu transmets le nombre converti à ton destinataire
3) le destinataire reçoit un nombre "réseau" et le reconverti en nombre local via une primitive "ntohs()" (Net to Host Short) ou "ntohl()" (Net to Host Long)
in_your_phion a écrit : Par ailleurs si je suis sur une machine little endian, est ce que je dois forcément décoder les donnés codées sur plusieurs octets et les remettre en Little endian ? |
Forcément. Mais la procédure ci-dessus est rodée pour ça...
Marsh Posté le 07-10-2011 à 07:21:34
<digression> Juste pour rebondir sur le fait que, en C++, boost::fusion permet d'iterer sur les membres d'une structures arbitraires a la façon d'un tuple générique</digression>
Marsh Posté le 07-10-2011 à 17:27:51
Sve@r a écrit : |
Sve@r a écrit : |
mERCI ! dOnc on pourrais résumé en disant que tout ce qui sors vers le net doit être converti en big endian, et tout ce qui arrive est supposé être du big endian, c'est ça ?
Marsh Posté le 07-10-2011 à 23:45:01
in_your_phion a écrit : mERCI ! dOnc on pourrais résumé en disant que tout ce qui sors vers le net doit être converti en big endian, et tout ce qui arrive est supposé être du big endian, c'est ça ? |
Je ne sais pas si le nombre qui sort de htons()/htonl() est du big-endian mais c'est l'idée. Effectivement l'important c'est que tout le monde adopte la même politique et que tout le monde sache qu'il reçoit via réseau un nombre standardisé (si tu penses qu'il est "big-endian" pourquoi pas...) et les fonctions ntohs()/ntohl() (qui sont locales à chaque plateforme) s'occupent du reste...
Marsh Posté le 08-10-2011 à 00:59:38
in_your_phion a écrit : |
la convention du net est de transmettre du big endian. Après, si tu as envie de faire le malin et de transmettre du little endian, tant que c'est en environnement contrôlé, pourquoi pas. C'est une convention, pas une obligation. Mais évidemment, les protocols standardisés respecteront certainement cette convention.
Marsh Posté le 09-07-2010 à 18:24:39
bonjour
est il possible d'afficher chaque bit (0 ou 1) sous forme d'entier, d'un entier ?
Par exemple, si j'ai un entier qui vaut 2 dans mon code, ça fait en binaire qque chose comme 000000 ... 10 (sur 32 bit j'imagine)
est ce que je peux afficher ça à l'écran ? (cad 0 0 ... 0 1 0)
merci par avance