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

时间:2016-08-26 19:45:10

标签: c++ c endianness

我正在重写从Big Endian Machine到Little Endian机器的代码。

我们假设有一个名为a的变量,它是一个32位整数,它保存当前时间戳(用户请求的当前时间戳)。

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

现在,当我为小端机器编写相同的逻辑时,我可以使用相同的代码(方法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);

我写了这个程序来验证:

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

}

结果:

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

看起来没有转换为大端序,相同的逻辑(没有htonl())给出了填充数组arr的确切结果。现在,如果我希望数组在小端和大端机器中都相同(或小端结果应该与大端结果完全相同),请问我是否可以使用htonl()或不使用{<1}}。

2 个答案:

答案 0 :(得分:2)

您最初编写的代码将在大端和小端机器上执行您想要的操作。

例如,如果a的值为0x00123456,则0x12进入arr[0]0x34进入arr[1],{ {1}}进入0x56。无论机器的字节顺序如何,都会发生这种情况。

当您使用arr[2]>>运算符时,它们会对相关表达式的进行操作,而不是表示值。

当您致电&时,您可以更改该值以匹配特定的表示。因此,在小端机htonl上将生成值htonl(0x00123456)。然后,当您对该值进行操作时,您会得到不同的结果。

当字节序很重要时,使用多个字节的数字的表示被读取或写入字节,即通过网络或通过网络或从字节缓冲区写入磁盘。

例如,如果你这样做:

0x56341200

然后,uint32_t a = 0x12345678; ... write(fd, &a, sizeof(a)); 组成的四个字节一次一个地写入文件描述符(无论是文件还是套接字)。大端机器将按顺序编写a0x120x340x56,而小端机器将编写0x780x780x560x34

如果您希望以一致的顺序写入字节,则在调用0x12之前首先调用a = htonl(a)。然后,字节将始终写为write0x120x340x56

因为您的代码对值而不是值的单个字节进行操作,所以您不必担心字节序。

答案 1 :(得分:0)

您应该使用htonl()。在big-endian机器上,它什么都不做,它只返回原始值。在小端机器上,它适当地交换字节。因此,通过使用它,您不必关心机器的字节序,您可以在调用后使用相同的代码。