字节序(大端/小端)

字节序与大小端

  • 字节是计算机内部的基本存储单元,一个数据通常由多个字节(Byte)构成。如int类型的变量,在32位系统中则由4个Byte组成,字节序则指存放在计算机内部的这4个Byte的存储顺序,顺序有两种:

如有int a = 0x12345678
(最低位(Most Least Bit)为16进制的8,是最低有效位;最低位(Most Significant)为16进制的1,是最高有效位)

  1. 低地址存储低地址字节,高地址存储高地址字节 -> 小端
  2. 低地址存储高地址字节,高地址存储低地址字节 -> 大端

如图1:
image

如图2:
image


平台与大小端

  • 不同架构的处理器,存储模式一般也不同。ARM、X86、DSP一般都采用小端模式,而IBM、Sun、PowerPC架构的处理器一般都采用大端模式

查看运行平台的大小端

#include <stdio.h>
int main()
{
    int a = 0x12345678;
    char b = a;
    // int类型变量占4个字节
    // char类型变量占4个字节
    // 当字节占用数较多的类型(如:int)给字节字节占用数较少的类型(如:char)赋值时,会发生“截断”
    // 即低字节的数据保留,高字节的数据被舍弃,所以可以利用这个原理查看变量a的字节序为大端还是小端
    if(b == 0x78)
    {
        printf("Little endian!\n");
    }
    else{
        printf("Big endian!\n");
    }
    return 0;
}

为什么不同架构的处理器在存储模式上会有大小端之分呢?

  • 小端模式低地址存储低字节数据,比较符合人类的思维习惯;
  • 大端模式则更适合计算机的处理习惯:不需要考虑地址和数据的对应关系,以字节为单位,把数据从左到右,按照由低到高的地址顺序直接读写即可。大端模式一般用在网络字节序、各种编解码中。作为一名嵌入式工程师,掌握大端模式与小端模式的存储方式很有必要。我们在驱动开发中配置各种寄存器,经常需要对某个寄存器的几个比特位进行读写操作。不同存储模式的嵌入式设备互联及网络数据传输,也需要考虑大小端模式,在处理网络数据时需要自己实现数据的大小端转换。如果你写的程序代码要在不同架构的嵌入式平台上运行(如ARM、PowerPC),还是要考虑大小端模式的转换的。

大小端的转换

在一个嵌入式系统软件中,如何实现大小端存储模式的转换呢?我们可以定义一个宏,将高、低地址上的数据互换,即可完成大小端存储模式的转换。
image
在Linux内核源码的头文件目录include/linux/byteorder下,有3个头文件big_endian.h、generic.h、little_endian.h。在这3个头文件中定义了各种宏,实现了不同类型数据的大小端存储模式的相互转换,大家在驱动开发或内核编程中可以直接使用这些封装好的API,不需要自己再重复定义了

Reference:

posted @ 2024-06-13 18:26  stitchCat  阅读(312)  评论(0)    收藏  举报