#Linux杂记--大端模式和小端模式

#Linux杂记--大端模式和小端模式

    • 引言
    • 问题
    • 解惑
    • 补充

引言

       这是一次 C 语言编程中有关内存操作的巨坑记录。


问题

       各位读者可以和我一起来思考以下这段小程序的输出:

int
main(void)
{
	uint32_t p = 0x12345678;
	uint8_t *t1 = (uint8_t *)&p;
	uint8_t *t2 = t1 + 1;
	uint8_t *t3 = t1 + 2;
	uint8_t *t4 = t1 + 3;
	printf("p:%x,t1:%x,t2:%x,t3:%x,t4:%x\n", p, *t1, *t2, *t3, *t4);
}

       以下为程序的输出,各位读者有没有产生什么疑问呢?
       


解惑

       这其实是 大小端模式 之间的区别,简单来说,世界上存在两种 CPU 一种是按照人类正常思维的方式存放数据的 大端模式(Big-Endian):数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中。
       还有一种就是有利于计算机处理的方式存放数据的 小端模式(Little-Endian):数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来。
       还有一种 网络字节顺序 同大端模式。
       综上所述,按照大端模式 p 的数据在内存中的存放方式为:

1    2    3    4    5    6    7    8
0001 0010 0011 0100 0101 0110 0111 1000
^         ^         ^         ^
t1        t2        t3        t4

       按照小端模式 p 的数据在内存中的存放方式为:

7    8    5    6    3    4    1    2
0111 1000 0101 0110 0011 0100 0001 0010
^         ^         ^         ^
t1        t2        t3        t4

       这时候大家能理解程序的输出了吧?hhh
       需要注意的是,所有的 Intel 系列和大部分 ARM 系列的 CPU 都是按照小端模式存储的。


补充

       分享一个按照小端模式正常读取数据的函数

/**
 * 从内存中按照小端模式读取数据
 *
 * @param base  要读取的内存首址
 * @param output 输出缓冲区
 * @param size  要读取的字节数
 * @return None
 */
void
read_little_endian(void *base, void *output, size_t size)
{
    size_t i;
    char t[size];
    char *base_ = (char *) base;
    char *output_ = (char *) output;
    for (i = 1; i <= size; i++) {
        t[size - i] = *base_;
        base_ += 1;
    }
    for (i = 0; i < size; i++)
        output_[i] = t[i];
}

你可能感兴趣的:(Linux,c语言,操作系统)