2016-08-26 2 views
1

Je suis en train de réécrire le code de Big Endian Machine à Little Endian. Disons qu'il existe une variable appelée a, qui est un entier de 32 bits qui contient l'horodatage actuel (horodatage actuel de la requête de l'utilisateur).Confusion dans l'interprétation de l'entier 32 bits dans les machines Big Endian et Little Endian

dans la machine Big Endian, maintenant le code est ainsi:

uint32 a = current_timestamp_of_user_request; 
uint8 arr[3] = {0}; 
arr[0] = ((a >> (8 * 2)) & 0x000000FF); 
arr[1] = ((a >> (8 * 1)) & 0x000000FF); 
arr[2] = ((a >> (8 * 0)) & 0x000000FF); 

Maintenant, quand je suis en train d'écrire la même logique pour petite machine endian, puis-je utiliser le même code (méthode a), ou devrais-je convertir le code de cette façon (appelons cette méthode b)?

uint32 a = current_timestamp_of_user_request; 
uint32 b = htonl(a); 
uint8 arr[3] = {0}; 
arr[0] = ((b >> (8 * 2)) & 0x000000FF); 
arr[1] = ((b >> (8 * 1)) & 0x000000FF); 
arr[2] = ((b >> (8 * 0)) & 0x000000FF); 

j'ai écrit ce programme pour vérifier:

#include<stdio.h> 
#include<stdlib.h> 


void main() { 
    long int a = 3265973637; 
    long int b = 0; 
    int arr[3] = {0,0,0}; 

    arr[0] = ((a >> (8 * 2)) & 0x000000FF); 
    arr[1] = ((a >> (8 * 1)) & 0x000000FF); 
    arr[2] = ((a >> (8 * 0)) & 0x000000FF); 

    printf("arr[0] = %d\t arr[1] = %d\t arr[2] = %d\n", arr[0], arr[1], arr[2]); 

    b = htonl(a); 

    arr[0] = ((b >> (8 * 2)) & 0x000000FF); 
    arr[1] = ((b >> (8 * 1)) & 0x000000FF); 
    arr[2] = ((b >> (8 * 0)) & 0x000000FF); 

    printf("After htonl:\n"); 
    printf("arr[0] = %d\t arr[1] = %d\t arr[2] = %d\n", arr[0], arr[1], arr[2]); 

} 

Résultats:

Result with little endian machine: 

bgl-srtg-lnx11: /scratch/nnandiga/test>./x86 
arr[0] = 170  arr[1] = 205 arr[2] = 133 
After htonl: 
arr[0] = 205  arr[1] = 170 arr[2] = 194 

Result with big endian machine: 
arr[0] = 170  arr[1] = 205 arr[2] = 133 
After htonl: 
arr[0] = 170  arr[1] = 205 arr[2] = 133 

On dirait sans conversion en grand ordre endian, la même logique (sans htonl()) donne des résultats exacts dans remplir le tableau arr. Maintenant, pouvez-vous s'il vous plaît répondre dois-je utiliser htonl() ou non si je veux que le tableau soit le même dans les deux petites machines endian et big endian (petit résultat endian devrait être exact comme résultat big endian).

+0

Si le but est de mettre l'octet le moins significatif de l'horodatage dans 'arr [2]', alors le code devrait être identique sur les deux machines. Les opérations de décalage et de masquage dans le code ne dépendent pas de l'endian. – user3386109

Répondre

2

Votre code comme écrit à l'origine fera ce que vous voulez sur les grosses machines endian et little little endian.

Si par exemple la valeur de a est 0x0, puis 0x12 va dans arr[0], 0x34 va dans arr[1] et 0x56 va dans arr[2]. Cela se produit indépendamment de ce que l'endianness de la machine est.

Lorsque vous utilisez les >> et & opérateurs, ils fonctionnent sur la valeur de l'expression en question, et non pas la représentation de cette valeur.

Lorsque vous appelez htonl, vous modifiez la valeur pour qu'elle corresponde à une représentation particulière. Donc, sur une petite machine d'Endian htonl(0x0) se traduira par la valeur 0x56341200. Ensuite, lorsque vous opérez sur cette valeur, vous obtenez des résultats différents. Lorsque l'importance est importante, c'est lorsque la représentation d'un nombre utilisant plusieurs octets est lue ou écrite en octets, c'est-à-dire sur un disque, sur un réseau ou sur/à partir d'un tampon d'octets.

Par exemple, si vous faites ceci:

uint32_t a = 0x12345678; 
... 
write(fd, &a, sizeof(a)); 

Ensuite, les quatre octets a se compose de sont écrits dans le descripteur de fichier (que ce soit un fichier ou un socket) un à la fois.Une grosse machine endian rédigera 0x12, 0x34, 0x56, 0x78 dans cet ordre tandis qu'une petite machine endian rédigera 0x78, 0x56, 0x34, 0x12.

Si vous souhaitez que les octets soient écrits dans un ordre cohérent, vous devez d'abord appeler le a = htonl(a) avant d'appeler le write. Ensuite, les octets seront toujours écrits comme 0x12, 0x34, 0x56, 0x78. Comme votre code fonctionne sur la valeur et non sur les octets individuels de la valeur, vous n'avez pas besoin de vous inquiéter de l'endianness.

0

Vous devez utiliser htonl(). Sur une machine big-endian, cela ne fait rien, cela renvoie simplement la valeur d'origine. Sur une machine little-endian, elle échange les octets de manière appropriée. Donc, en utilisant ceci, vous n'avez pas à vous soucier de l'endianité de la machine, vous pouvez utiliser le même code après l'avoir appelé.

+0

C'est la même chose pour C++, donc j'ai annulé votre 1ère édition. –

+0

Son code utilise 'printf()' plutôt que 'cout', donc il ressemble à C. Mais vous avez raison de dire que la partie pertinente de la question est la même pour la plupart des dialectes C. – Barmar

+0

Bien que la solution soit la même pour C++. –