Comment les données sont-elles stockées au niveau du bit en fonction de «Endianness»?

J’ai lu sur Endianness et compris squat …

alors j’ai écrit ça

main() { int k = 0xA5B9BF9F; BYTE *b = (BYTE*)&k; //value at *b is 9f b++; //value at *b is BF b++; //value at *b is B9 b++; //value at *b is A5 } 

k était égal à A5 B9 BF 9F

et (octet) pointeur ” promenade ” o / p était 9F BF b9 A5

donc je reçois les octets sont stockés à l’envers … ok.

~

alors maintenant je pensais comment est-il stocké au niveau BIT …

Je signifie que “9f” (1001 1111) est enregistré sous “f9” (1111 1001)?

alors j’ai écrit ça

 int _tmain(int argc, _TCHAR* argv[]) { int k = 0xA5B9BF9F; void *ptr = &k; bool temp= TRUE; cout<<"ready or not here I come \n"<<endl; for(int i=0;i<32;i++) { temp = *( (bool*)ptr + i ); if( temp ) cout<<"1 "; if( !temp) cout<<"0 "; if(i==7||i==15||i==23) cout<<" - "; } } 

Je reçois une sortie aléatoire

même pour nos. comme “32” je ne reçois rien de raisonnable.

Pourquoi ?

La finalité , comme vous l’avez découvert lors de votre expérience, fait référence à l’ordre dans lequel les octets sont stockés dans un object.

Les bits ne sont pas stockés différemment, ils sont toujours 8 bits et toujours “lisibles par l’homme” (haut-> bas).

Maintenant que nous avons discuté du fait que vous n’avez pas besoin de votre code … À propos de votre code:

 for(int i=0;i<32;i++) { temp = *( (bool*)ptr + i ); ... } 

Cela ne fait pas ce que vous croyez faire. Vous parcourez plus de 0 à 32, le nombre de bits d'un mot - bon. Mais votre affectation temp est tout faux 🙂

Il est important de noter qu'un bool* la même taille qu'un int* la même taille qu'un BigStruct* . Tous les pointeurs sur le même ordinateur ont la même taille: 32 bits sur un ordinateur 32 bits et 64 bits sur un ordinateur 64 bits.

ptr + i ajoute i octets à l'adresse ptr . Quand i>3 , vous lisez un nouveau mot ... cela pourrait éventuellement causer une erreur de segmentation.

Ce que vous voulez utiliser, ce sont des masques binarys . Quelque chose comme ça devrait marcher:

 for (int i = 0; i < 32; i++) { unsigned int mask = 1 << i; bool bit_is_one = static_cast(ptr) & mask; ... } 

Juste pour être complet, les machines sont décrites en termes d’ordre des octets et des bits.

L’intell x86 s’appelle Consistent Little Endian car il stocke les valeurs multi-octets dans l’ordre LSB à MSB à mesure que l’adresse mémoire augmente. Sa convention de numérotation des bits est b0 = 2 ^ 0 et b31 = 2 ^ 31.

Le Motorola 68000 est appelé Big Endian incohérent car il stocke les valeurs multi-octets dans l’ordre MSB à LSB à mesure que l’adresse mémoire augmente. Sa convention de numérotation des bits est b0 = 2 ^ 0 et b31 = 2 ^ 31 (idem que intel, raison pour laquelle il est appelé Big Endian ‘Inconsistent’).

IBM / Motorola PowerPC 32 bits s’appelle Consistent Big Endian car il stocke les valeurs multi-octets dans l’ordre MSB à LSB lorsque l’adresse de la mémoire augmente. Sa convention de numérotation des bits est b0 = 2 ^ 31 et b31 = 2 ^ 0.

En langage normal de haut niveau, l’ordre des bits est généralement transparent pour le développeur. Lorsque vous écrivez en langage assembleur ou que vous utilisez du matériel, la numérotation des bits entre en jeu.

Votre machine ne peut presque certainement pas traiter des bits individuels de la mémoire. La disposition des bits dans un octet n’a donc pas de sens. L’endianisme fait uniquement référence à l’ordre des octets dans des objects multi-octets.

Pour donner du sens à votre deuxième programme (bien qu’il n’y ait aucune raison de le faire, car il ne vous donnera aucun résultat significatif), vous devez en savoir plus sur les opérateurs au niveau des bits – en particulier pour cette application.

Byte Endianness

Sur différentes machines, ce code peut donner des résultats différents:

 union endian_example { unsigned long u; unsigned char a[sizeof(unsigned long)]; } x; xu = 0x0a0b0c0d; int i; for (i = 0; i< sizeof(unsigned long); i++) { printf("%u\n", (unsigned)xa[i]); } 

En effet, différentes machines sont libres de stocker des valeurs dans l'ordre des octets qu'elles souhaitent. C'est assez arbitraire. Il n'y a pas d'arrière ou d'avant dans le grand schéma des choses.

Bit Endianness

Habituellement, vous n'avez pas à vous soucier de l'endurance des bits. Le moyen le plus courant d'accéder à des bits individuels est d'utiliser des décalages ( >> , << ), mais ceux-ci sont réellement liés à des valeurs, et non à des octets ou à des bits. Ils effectuent une opération arithmatique sur une valeur. Cette valeur est stockée en bits (qui sont en octets).

Si vous utilisez un champ de bits, vous pouvez rencontrer un problème d’endianisme en bits en C. C'est une "fonctionnalité" de C rarement utilisée (pour cette raison et quelques autres) qui vous permet d'indiquer au compilateur le nombre de bits qu'un membre d'une struct utilisera.

 struct thing { unsigned y:1; // y will be one bit and can have the values 0 and 1 signed z:1; // z can only have the values 0 and -1 unsigned a:2; // a can be 0, 1, 2, or 3 unsigned b:4; // b is just here to take up the rest of the a byte }; 

Dans ce cas, le bit endianness dépend du compilateur. Doit-il être le bit le plus ou le moins significatif dans une thing ? Qui sait? Si vous vous souciez de l'ordre des bits (décrivant des choses telles que la disposition d'un en-tête de paquet IPv4, des registres de contrôle de périphérique ou tout simplement un format de stockage dans un fichier), vous ne voudrez probablement pas vous inquiéter d'un compilateur différent qui le ferait mal façon. De plus, les compilateurs ne sont pas toujours aussi intelligents qu'ils le souhaiteraient avec les champs de bits.

Cette ligne ici:

 temp = *( (bool*)ptr + i ); 

… quand vous faites une arithmétique de pointeur comme celle-ci, le compilateur déplace le pointeur d’un nombre que vous avez ajouté multiplié par la taille de l’élément que vous pointez . Parce que vous lancez votre vide * dans un bool *, le compilateur déplacera le pointeur de la taille d’un “bool”, qui est probablement juste un int sous les couvertures, vous imprimerez ainsi de la mémoire plus loin. que vous avez pensé.

Vous ne pouvez pas adresser les bits individuels dans un octet, il est donc presque inutile de demander dans quel sens ils sont stockés. (Votre machine peut les stocker comme bon vous semble et vous ne pourrez pas le savoir). La seule fois où cela peut vous intéresser est de cracher des bits sur une interface physique telle que I2C, RS232 ou similaire, où vous devez les cracher un par un. Même dans ce cas, cependant, le protocole définirait l’ordre dans lequel cracher les bits et le code du pilote de périphérique devrait être converti entre “un entier de valeur 0xAABBCCDD” et “une séquence de bits 11100011 … [peu importe] dans l’ordre du protocole “.