大端存储和小端存储(转)

在CPU内部的地址总线和数据总线是与内存的地址总线和数据总线连接在一起的。当一个数从内存中向CPU传送时,有时是以字节为单位,有时又以字(4字节)为单位。传过来是放在寄存器里(一般是32字节),在寄存器中,一个字的表示是右边应该属于低位,左边属于高位,如果寄存器的高位和内存中的高地址相对应,低位和内存的低地址相对应,这就属于小端存储。反之则称为大端存储。大部分处理器都是小端存储的。

因为十六进制的2位正好是1字节,所以选十六进制0x0A0B0C0D为例,如图2-1所示,对小端存储,低位是0x0D,应存入低位地址,所以存入的顺序是

0x0D 0x0C 0x0B 0x0A

反之,对于大端存储则为

0x0A 0x0B 0x0C 0x0D

  

                                                                   图解大端和小端存储

下面利用union的成员共有地址的性质,用一个程序来具体说明小端存储。

#include <stdio.h>
union s{
        int a;        //所有成员用在内存中位置相同
        char s1[4];   //访问时,根据变量的类型决定内存中的内容被如何解释
}uc;
int main( )
{
    int i=0;
    uc.a=0x12345678;
    printf("0x%x\n",&uc);
    for(i=0;i<4;i++)
        printf("0x%x 0x%x\n",&uc.s1[i],uc.s1[i]);
    return 0;
}


声明十六进制整数a,它与字符串数组共有地址,a的最低字节是0x78,按小端存储,则应存入“&uc.s1[0]”中,也就是0x405050中,最高位地址0x405051则应存入0x56,也就是数据的高位。下面的运行结果证明了这一点。其实,可以在调试环境中直接看到这些结果。



请注意,两水平线之间的内容和原文不太一样,个人不太认同书中解答,所以略微修改一番,详情请看C语言解惑 刘振安 刘燕君 编著著 的指针基础知识章节

另外,书中程序在编译时候会产生警告,对于追求 0 error(s), 0 warning(s) 的可以在相应语句中添加 (unsigned int) 将类型强制转换成无符号整型,因为 %x的期望类型是unsigned int ,并将其以十六进制方式打印出来。

下面,分享一道有趣的编程题,加深印象,此题来自<<C语言深度解剖>>

在32位的X86系统下,输出的值为:

#include <stdio.h>
int main()
{
    int a[5]={1,2,3,4,5};            //A
    int *ptr1=(int *)(&a+1);         //B
    int *ptr2=(int *)((int)a+1);     //C

    printf("%x,%x",ptr1[-1],*ptr2);  //D
    return 0;
}

首先,由题目可知32位的X86系统是采用小端存储的,即高位放高地址,低位放地址。执行完A语句后,假设该数组是放在0起始地址上。那么可画出内存图如下,额没有专业电脑笔,就酱汁吧,(或者大家推荐个好用的绘图软件也不错,嘿)

&a+1是整个数组长度再加1,指向20地址,而&a[0]+1则是指向2地址,虽然&a与&a[0]地址一样,但是有着本质的不同。ptr1[-1]被解析成*(ptr1-1),即ptr1往后退四字节,所以ptr1[-1]十六进制为5。对于C赋值语句,(int)a+1指向的地址为1,因为是低端存储,所以*ptr2=2000000,以上,完毕。

答案:5,2000000

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值