大端小端问题总结


首先对于内存读写来说,不管什么模式,cpu在读取和存储数据的时候一定都是从内存的低地址依次向高地址读取或写入。(换句话说,硬件只能完成收到一串数据后,从内存的低地址到高地址依次写入)

大小端问题:

要明白大小端都是以octet位最小单位

小端:

指的是数据的高字节保存在内存的高地址中,比如0x12345678中的"0x12"为高字节,所以保存方式是

MEM AddrData
0x000x78
0x010x56
0x020x34
0x030x12
0x040xcc

在小端模式中,计算机的存放和读取都是从高地址向低地址读取,所以如上表格从上到下读取,分别读取的数据为0x78 0x56 0x32 0x12,如x86是小端模式。

大端:

是指数据的高字节保存在内存的低地址中,如下表格,分别读取的数据为0x12 0x34 0x56 0x78,如power PC是大端模式。

MEM AddrData
0x000x12
0x010x34
0x020x56
0x030x78
0x040xCC

现在假设A(大端模式)存储如上图的数据,他将数据发送给B(小端模式),
该数据在A中为0x12345678(因为高字节保存在内存低地址中)。B接受到的数据依次是0x12,0x34,0x56,0x78,0x12先收到存在低地址处,然后再0x34,0x56,0x78,发送完毕后,该数据在B中的内存分布和A中一样(所以真是情况下需要软件进行大小端转换)。

不管大小端,对于一串字符0x12345678都是会先存放或读取0x78高字节的,不过对于小端模式来说它是向上生长的(从内存高地址到低地址),所以它的0x78高字节会放到高地址;而对于大端模式相反,它是向下生长的(从内存低地址到内存高地址),所以它的0x78会放到低地址。

对于大多数常见的CPU架构(x86、x86-64、ARM),数据的读取和存储通常都遵循从内存的低地址向高地址读取或者写入的规则。这是因为这种内存访问模式与计算机的内存存储方式以及大多数编程语言中的数据结构和数组的布局方式相一致。这种内存访问模式在大多数通用计算机架构中都是普遍的。

判断机器的字节序
BOOL IsBigEndian()  
{  
    int a = 0x1234;  
    /* 通过将int强制类型转换成char单字节,通过判断起始存储位置。即等于 取b等于a的低地址部分 */
    char b =  *(char *)&a;
    if( b == 0x12)  
    {  
        return TRUE;  `在这里插入代码片`
    }  
    return FALSE;  
}

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

BOOL IsBigEndian()
{
    union NUM
    {
        int a;
        char b;
    }num;
    num.a = 0x1234;
    if( num.b == 0x12 )
    {
        return TRUE;
    }
    return FALSE;
}
常见架构或传输的字节序

小端: x86、DEC、以太网、蓝牙
大端: PowerPC、IBM、Sun

大小端的常用转换

对于字(16位)

#define BigtoLittle16(A)   (( ((uint16)(A) & 0xff00) >> 8)    | \
                                       (( (uint16)(A) & 0x00ff) << 8))

对于双字(32位)

#define BigtoLittle32(A)   ((( (uint32)(A) & 0xff000000) >> 24) | \
                                       (( (uint32)(A) & 0x00ff0000) >> 8)   | \
                                       (( (uint32)(A) & 0x0000ff00) << 8)   | \
                                       (( (uint32)(A) & 0x000000ff) << 24))

内存生长方向问题

总听说向上生长、向下生长,什么意思呢?

堆没有方向,每个堆都是散落的;
堆和栈也没有谁的地址高低,都看操作系统的实现;
数据取下标偏移总是往上涨的,和在堆还是栈没啥关系。

栈是一种LIFO(Last In First Out)的结构。支持PUSH和POP两个操作。

对于向下生长,意思就是栈底在内存的低地址,栈顶在高地址,数据从内存低地址到高地址累计。
对于向上生长,意思就是栈底在内存高地址,栈顶在低地址,数据从内存高地址向低地址累计。

参考文章

  1. https://blog.csdn.net/weixin_45633061/article/details/117421452#%E6%A6%82%E8%A7%88
  2. https://zhuanlan.zhihu.com/p/275662870
  3. https://blog.csdn.net/lwz15071387627/article/details/88185196
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值