大小端模式

承接《数组指针和指针数据》最后有个关于大小端的问题

上面这个问题似乎还没啥技术含量,下面就来个有技术含量的:在x86 系统下,其值为多少?
int main()
{
   int a[4]={1,2,3,4};
   int *ptr1=(int *)(&a+1);//指向a数组后面的内存单元,&a+1表示向后移16个存储单元
   int *ptr2=(int *)((int)a+1);//表示a的存储单元的地址增加一个字节
   printf("%x,%x",ptr1[-1],*ptr2);//ptr1[-1]其实指向的是a数组的最后一个单元,*ptr1则表示a数组的地址后移一个字节之后的4个连续存储单元所存储的值
   return 0;
}


其内存布局如下图:

大小端模式

  编辑
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
例子 

int num1 = 1;

num1 补码 0x00000001

大端模式(Big-endian模式)内存存储次序 0x00000001 

小端模式(Little-endian模式)内存存储次序0x01000000


实体测试大小端模式

示例代码

#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
    int a[4] = { 1,2,3,4 };
    int *ptr1 = (int *)(&a + 1);//指向a数组后面的内存单元,&a+1表示向后移16个存储单元
    int *ptr2 = (int *)((int)a + 1);//表示a的存储单元的地址增加一个字节

    cout << ptr1[-1] << endl;//ptr1[-1]其实指向的是a数组的最后一个单元,*ptr1则表示a数组的地址后移一个字节之后的4个连续存储单元所存储的值
    cout << *ptr2 << endl;

    cout << *ptr1 << endl;

    return 0;
}
运行系统64位 win7,编译器visual studio2015 x86 运行结果:



看一下内存地址


从内存中可以看出该模式是小端模式

&a 是整个数组的首地址,a是数组首元素的首地址(参考《数组指针和指针数据》)

ptr1 = a + 16

ptr2 =  a + 1

ptr2 为什么等于33554432呢?

ptr2内存如下图


由于该模式是小端模式,*ptr2补码是 0x02000000 转为二进制则是33554432


怎样判断当前操作系统是什么模式呢

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

bool checkCPU()
{
    union w
    {
        int a;
        char b;
    } c;
    c.a = 1;
    return(c.b == 1);
}


---------------------------------------------------------------------------------

扩展

x86结构的计算机使用的都是小端模式。一般来说,大部分用户的操作系统(如windows,FreeBSD,linux)都是小端模式。少部分,如MAC OS是大端模式

在网络上传输数据时,由于数据传输的两端对应不同的硬件平台,采用的存储字节顺序可能不一致。因此在TCP/IP协议规定了在网络上必须采用网络字节顺序,也就是大端模式。
对于char型数据只占一个字节,无所谓大端和小端。而对于非char类型数据,必须在数据发送到
网络上之前将其转换成大端模式。接收网络数据时按符合接受主机的环境接收。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值