字节序及字节序转换


概念

字节序,即多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。 来自百度百科

可分为小端字节序和大端字节序。

小端字节序(Little Endian, LE),低字节存储在内存低地址;高字节存储在内存高地址。
大端字节序(Big Endian, BE),低字节存储在内存高地址;高字节存储在内存低地址。网络字节序采用的就是大端字节序。

例如:把0x1234,两个字节的数据写入到0x34230000起始的内存中。
使用小端字节序:
0x34存储在0x34230000中
0x12存储在0x34230001中
在内存中存储如下:
低|00110100|00010010|高
使用大端字节序:
0x12存储在0x34230000中
0x34存储在0x34230001中
在内存中存储如下:
低|00010010|00110100|高


检测

程序

此程序在int为占2字节以上的编译器上执行,下面示例的说明是在int为4字节的编译器上执行的结果

// 若处理器采用的是大端模式,则返回0;若采用的是小端模式,则返回1。
int checkCPU()
{
    union
    {
        int a;
        char b;
    } c;
    
    c.a = 1;
    return c.b==1;
}

剖析

由于联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性就可以轻松地获得了CPU对内存采用Little-Endian还是Big-Endian模式读写。

说明

1、 在c中,联合体(共用体)的数据成员都是从低地址开始存放;
2、 若是小端模式,由低地址到高地址c.a存放为0x01 00 00 00,c.b被赋值为0x01;

地址 0x00000000 0x00000001 0x00000002 0x00000003
c.a 01 00 00 00
c.b 01 00

3、 若是大端模式,由低地址到高地址c.a存放为0x00 00 00 01,c.b被赋值为0x0;

地址 0x00000000 0x00000001 0x00000002 0x00000003
c.a 00 00 00 01
c.b 00 00

4、 根据c.b的值的情况就可以判断cpu的模式了。


转换

程序

#include 
#include 

// 32位int大小端转换
int32_t BigLittleSwap32(int32_t value)
{
    return ((value & 0x000000FF) << 24 |
            (value & 0x0000FF00) << 8  |
            (value & 0x00FF0000) >> 8  |
            (value & 0xFF000000) >> 24 );
}

// 64位int大小端转换
int64_t BigLittleSwap64(int64_t value)
{
    return ((value & 0x00000000000000FF) << 56 |
            (value & 0x000000000000FF00) << 40 |
            (value & 0x0000000000FF0000) << 24 |
            (value & 0x00000000FF000000) << 8  |
            (value & 0x000000FF00000000) >> 8  |
            (value & 0x0000FF0000000000) >> 24 |
            (value & 0x00FF000000000000) >> 40 |
            (value & 0xFF00000000000000) >> 56);
}

int main()
{
    int aaa = 0x1234;
    printf("aaa = %d\n", aaa);
    int bbb = BigLittleSwap32(aaa);
    printf("bbb = %d\n", bbb);
    int64_t ccc = BigLittleSwap64(aaa);
    printf("ccc = %ld\n", ccc);
    
    return 0;
}

你可能感兴趣的:(字节序及字节序转换)