简体   繁体   English

在Big Endian和Little Endian机器中解释32位整数时的混乱

[英]Confusion in interpreting 32 bit integer in Big Endian and Little Endian Machines

I am in process of rewriting code from Big Endian Machine to Little Endian machine. 我正在将代码从Big Endian Machine重写到Little Endian Machine。

Let's say there is a variable called a , which is a 32 bit integer which holds current timestamp(user request's current timestamp). 假设有一个名为a的变量,它是一个32位整数,保存当前时间戳(用户请求的当前时间戳)。

In Big Endian machine, right now the code is this way: 在Big Endian机器中,现在的代码是这样的:

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);

Now, when I am writing the same logic for little endian machine, can I use the same code(method a), or should I convert the code this way(let's call this method b)? 现在,当我为小端机器编写相同的逻辑时,我可以使用相同的代码(方法a),还是应该以这种方式转换代码(让我们将此方法称为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);

I wrote this program to verify: 我写了这个程序来验证:

#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]);

}

Results: 结果:

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

Looks like without conversion to big endian order, the same logic(without htonl() ) gives exact results in filling the array arr . 看起来好像没有转换为大端序,相同的逻辑(没有htonl() )在填充数组arr给出确切的结果。 Now, can you please answer should I use htonl() or not if I want the array to be the same in both little endian and big endian machines(little endian result should be exact as big endian result). 现在,如果我希望小端字节序和大端字节序计算机中的数组都相同(小端字节结果应与大端字节结果完全一样htonl() ,请问我是否应该使用htonl() )。

Your code as originally written will do what you want on both big endian and little endian machines. 最初编写的代码将在大型字节序和小型字节序计算机上完成您想要的操作。

If for example the value of a is 0x00123456 , then 0x12 goes in arr[0] , 0x34 goes in arr[1] , and 0x56 goes in arr[2] . 例如,如果a值为0x00123456 ,则0x12进入arr[0]0x34进入arr[1] ,而0x56进入arr[2] This occurs regardless of what the endianness of the machine is. 无论机器的字节序如何,都会发生这种情况。

When you use the >> and & operators, they operate on the value of the expression in question, not the representation of that value. 当您使用>>&运算符时,它们将运算所讨论表达式的 ,而不是该值的表示形式

When you call htonl , you change the value to match a particular representation. 调用htonl ,您可以更改值以匹配特定的表示形式。 So on a little endian machine htonl(0x00123456) will result in the value 0x56341200 . 因此,在小端机上, htonl(0x00123456)的值0x56341200 Then when you operate on that value you get different results. 然后,当您对该值进行运算时,您会得到不同的结果。

Where endianness matters is when the representation of a number using multiple bytes is read or written as bytes, ie to disk, over a network, or to/from a byte buffer. 字节顺序重要的地方是使用多个字节的数字表示形式作为字节读取或写入,即通过网络或到/从字节缓冲区读取或写入到磁盘。

For example, if you do this: 例如,如果您这样做:

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

Then the four bytes that a consists of are written to the file descriptor (be it a file or a socket) one at a time. 然后,由a组成的四个字节a写入一个文件描述符(文件描述符或套接字)。 A big endian machine will write 0x12 , 0x34 , 0x56 , 0x78 in that order while a little endian machine will write 0x78 , 0x56 , 0x34 , 0x12 . 大端机器会写0x120x340x560x78的顺序而小端机器会写0x780x560x340x12

If you want the bytes to be written in a consistent order then you would first call a = htonl(a) before calling write . 如果要以一致的顺序写入字节,则应先调用a = htonl(a)然后再调用write Then the bytes will always be written as 0x12 , 0x34 , 0x56 , 0x78 . 那么字节将始终被写为0x120x340x560x78

Because your code operates on the value and not the individual bytes of the value, you don't need to worry about endianness. 因为您的代码在值上而不是值的单个字节上进行操作,所以您不必担心字节顺序。

You should use htonl() . 您应该使用htonl() On a big-endian machine this does nothing, it just returns the original value. 在big-endian计算机上,此操作不执行任何操作,仅返回原始值。 On a little-endian machine it swaps the bytes appropriately. 在小端机上,它会适当地交换字节。 So by using this, you don't have to concern yourself with the endian-ness of the machine, you can use the same code after calling it. 因此,通过使用此代码,您不必担心计算机的字节序,可以在调用它之后使用相同的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM