【计算机组成】大端与小端

发布时间 2023-07-11 16:43:47作者: hsjjj

在计算机系统中,内存的每一个字节都被赋予地址值作为唯一标识。

对于一个字节来说,它的最低有效位(LSB, Least Significant Bit)位于二进制最右边,而最高有效位(MSB, Most Significant Bit)位于二进制最左边。这一点对于所有的计算机系统架构都是一致的。即如果用一个字节存储十进制数13,字节的值为0b00001101

然而,更多的数据类型的大小不止一个字节。比如,c语言中long占4个字节。这时如果我用一个long *指针指向一个long类型的变量,实际上是指向两个字节中地址值较低的那个。这一点可以通过如下代码印证:

// seeBytesOfLong.c
int main() {
        long num = 0x12345678;
        long* long_ptr = #
        unsigned char* ptr = (unsigned char*) long_ptr;
        for(int i = 0; i < 4; i++) {
                printf("%p\n", ptr);
                ptr++;
        }
        return 0;
}

执行结果如下:

这时就出现了一个问题,用这样的由多个字节组成的类型来存储值时,值的高位存放在低地址字节,还是高地址字节呢?这两种方案实际都是可行的,这也就是所说的大端与小端。

大端与小端指的就是数据的存储方式。具体而言,大端指的是将高位数据字节存放在低地址处,而小端指的是将高位数据字节存放在高地址处。

也就是说,如果我用long型存储0x12345678,那么在大端的模式下,地址由低到高四个字节存储的值分别为0x12, 0x34, 0x56, 0x78,而小端模式下,存储的值会反过来,依次为0x78, 0x56, 0x34, 0x12

实际的存储方式为小端还是大端呢?这取决于计算机架构,即由硬件决定。

对于x86_64架构,其采取的数据存储方式是小端方式。基于验证long型字节地址顺序的代码略作改动即可印证:

// seeBytesOfLong.c
#include<stdio.h>

int main() {
        long num = 0x12345678;
        long* long_ptr = &num;
        unsigned char* ptr = (unsigned char*) long_ptr;
        for(int i = 0; i < 4; i++) {
                printf("%p: %x\n", ptr, *ptr);
                ptr++;
        }
        return 0;
}

执行后,输出如下:

可以看到,低位数据字节确实位于低地址。