
加3g实验室的艰难之旅,遇到一道这样的实验室面试题:
输出结果为2000000
原题对a强制转换为int,64位机指针长度为八个字节,所以改为long int。
先来分析一下表达式,a为数组a[0]的地址,强制转换为长整型变为地址的数值后加一,实际为第一个元素的第二字节地址的数值。后转换为一指向整型的指针并赋值给ptr2。整型为4个字节,从第一元素第二字节开始往后读取四个字节,间接访问得出此四个字节代表的数值,并以十六进制输出。
那么问题来了,为什么是2000000,数组的整型元素在内存中是怎么储存的?这四个字节内存的是怎样的二进制数?为什么会这样储存?
经过度娘的帮助,它终于出现了—— 大小端模式 。
大端模式
大端模式是指数据的高位,保存在内存的低地址中,而数据的低位,保存在内存的高地址中。大端模式与我们的阅读习惯相同。
小端模式
小端模式是指数据的高位保存在内存的高地址中,而数据的低位保存在内存的低地址中。
举例
int a=2;
地址:小----->大
在大端模式中,a存为:
0x00 0x00 0x00 0x02
在小端模式中,a存为:
0x02 0x00 0x00 0x00
在计算机系统中,地址是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了一个字节(8bit)的char之外,还有两个字节(16bit)的short型等超过一个字节的数据类型。另外,对于位数大于 8位的处理器,由于寄存器宽度大于一个字节。所以必然存在如何将多个字节安排的问题,因此就有了大端存储模式和小端存储模式。
小说《格列夫游记》中,小人国内部分裂成Big-endian和Little-endian两派,区别在于一派要求从鸡蛋的大头把鸡蛋打破,另一派要求从鸡蛋的小头把鸡蛋打破。斯威夫特借以讽刺英国的政党之争,在计算机工业中指数据储存顺序的分歧。
一个简单的判断数据储存模式为大端模式还是小端模式。
a[5] = {1,2,3,4,5};
第一个元素和第二个元素储存方式
(地址:小--->大)
大端模式下:
0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x02
小端模式下:
0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00
截取第二个字节到第五个字节
大端模式:
0x00 0x00 0x01 0x00
小端模式:
0x00 0x00 0x00 0x02
读取数据
大端模式:
从高地址往低地址读取
0x00 0x00 0x01 0x00
读取数据转换为十六进制为100
小端模式:
从低地址往高地址读取
0x00 0x00 0x00 0x02
排成大端(0x02 0x00 0x00 0x00)
读取数据转换为十六进制为2000000
所以在大端模式下,结果为100。
在小端模式下,结果为2000000。
学C学得好迷啊,心好累,哈哈哈哈哈。
是。
大小端的概念
大小端的问题主要是由计算机内存中多字节形数据类型的存在而引起的,他的研究单位是字节,对于char行数据类型,就是一个字节,八位,是不存在大小端问题的;但是对于short、int、float等数据类型,表示一个数据需要多个字节,那么这多个字节之间的顺序就十分重要了。
Big-Endian和Little-Endian的定义如下:
Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
①大端模式://符合正常读写思维
低地址 -----------------> 高地址
0x12 | 0x34 | 0x56 | 0x78
②小端模式:
低地址 ------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12
③举例如下:
④大端小端没有谁优谁劣,各自优势便是对方劣势:
大端: ※符号位在所表示的数据的内容的第一个字节中,便于快速判断数据的正负(offset(0))和大小。
小端:易于进行数据类型转换,1、 2、 4字节的存储方式一样。
※低地址放低字节,所以在强制转换时不需要调整字节的内容
① 所谓小端存储,就是低地址存储低字节。例如一个32位的数据0x12345678,在存储器中指定地址依次保存为 0x78、0x56、0x34、0x12。如果老师教给你们的程序需要从8位接口的NOR中读数据并直接拼装,顺序读或逆序读其实都是可以的,反正程序里都要完成拼装。
② 连续读取的时候一般地址递增。不过这也不一定,要看你的实际需求而定。
要说到这个问题得从由鸡蛋引起的争端开始,话说在远古欧洲大陆有两个小人国,一个叫利立浦特(以下简称A国),一个叫不来夫斯库(以下简称B国)。
两个国家本来吃鸡蛋本来都是先从大的一端开始吃的,一直相安无事。直到有一天,A国国王的祖父小时候在一次吃鸡蛋时把手指划破了,祖父的父亲也就是当时的国王就下了一道命令,今后吃鸡蛋都要从小的一端开始吃起,违者重罚。此令一出,A国国内顿时民怨沸腾,人心不稳。B国说我也要来插一脚,指责A国违背上帝的旨意,我要替天行道,于是乎一场血战就开始了。
你是来讲故事的吗?我TM是来看计算机大小端的问题,你再跟我开玩笑吧!别急啊,话说在战争发生的100多年以后有个叫Danny Cohen的大胡子兄弟写了一篇“散文”《论圣战以及对和平的祈祷》。作者巴拉巴拉了一堆就此把大小端这个名词引入计算机界。虽然没大看懂,但是作者最后一段话还是很有道理的,不管先吃鸡蛋哪头都没有关系,但是我们每个人必须坚持以同样的方式去做事。我们可以选择任何一种方式活着,但必须做出决定,并坚持的活下去。但是老铁还想告诉你们,你可以按照自己的方式活着,但人是群居动物,当你需要和别人交流的时候,你必须适当的伪装一下,让别人能够接受。
其实在计算机界的大小端问题也是如此,著名的CPU两大派系,PowerPC系列采用大端(big endian)的方式存储数据,而X86系列则采用小端(little endian)方式存储数据。很显然如果你的程序只运行在PowerPC系列的CPU上,你完全可以不管什么是little endian,但是如果你PowerPC上的程序要和X86上的程序打交道,那么你就必须进行转换才能相互识别,不然那是要打架的。看见没有,计算机世界尽是与现实生活如此相似。
那么问题来了,看到这里,我们只知道大端是鸡蛋大的一端,小端指的是鸡蛋小的一端,那在计算机世界,这2个名词又代表什么意思呢,我们又该怎样去理解它呢?
1) 首先我们应该知道数据在计算机中是以二进制形式存储的,1个字节有8位,每1位的值只能是0或者1;
2) 其次我们还应该知道一个4位的二进制数和十六进制是1-1对应的,那么1个字节就可以拆分成2位的十六进制数;
3) 再其次我们还应该知道像0x1234abcd这样一个16进制数在内存中它是以4个字节存储的,既然这个数据在内存中跨越了多个字节,那么它肯定是有顺序的,我们叫它字节序。
4) 再再其次我们还应该知道这里的端指的是数据的尾端,大指的是高内存地址,小指的是低内存地址
那么问题就清楚了,所谓的大小端就是指字节序在内存中是如何存储的。大端指的就是把字节序的尾端(0xcd)放在高内存地址,而小端指的就是把字节序的尾端(0xcd)放在低内存地址,所以正确的叫法应该是 高尾端 和 低尾端。
在计算机系统中,存储是以字节为单位的,每个地址单元都对应着一个字节,一个字节=8bit。在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,如何安排多个字节的存储,这就有了大端存储模式和小端存储模式。
小端:较高的有效字节存放在较高的的存储器地址,较低的有效字节存放在较低的存储器地址。
大端:较高的有效字节存放在较低的存储器地址,较低的有效字节存放在较高的存储器地址。
如果将一个16位的整数0x1234存放到一个短整型变量(short)中。这个短整型变量在内存中的存储在大小端模式由下表所示。
C语言判断大小端模式
方法一:
voidIsBigEndian()
{
shortinta=0x1122; //十六进制,一个数值占4位charb = (char)&a;//通过将short(2字节)强制类型转换成char单字节,b指向a的起始字节(低字节)
if( b ==0x11) //低字节存的是数据的高字节数据
{
//是大端模式
}
else
{
//是小端模式
}
}
方法二:
voidIsBigEndian() //原理:联合体union的存放顺序是所有成员都从低地址开始存放,而且所有成员共享存储空间
{
uniontemp
{
shortint a;
char b;
}temp;
tempa=0x1234;
if(tempb==0x12) //低字节存的是数据的高字节数据
{
//是大端模式
}
else
{
//是小端模式
}
}
参考:>
网络字节序与大小端相辅相成,共同作用使 *** 作任务完成。
由于不同的系统会有不同的模式,为了统一,规定在网络传输中使用大端模式,这就是网络字节序。统一将网络上传输的字节序采用同一种模式,这样收发数据时,就会根据主机对应的模式是否和网络字节对应的模式一致,来判断是否需要进行转换。这样即使不同的设备使用不同的模式,网络传输不会出现问题。
1、二进制文本使用fopen函数的二进制模式“rb”就可以打开。对于程序来说,不管后缀名如何,文件分为两种类型:文本文件和二进制文件。 C语言里有一系列文件 *** 作函数。区分文本和二进制文件,需要在打开文件时设置不同的控制符mode的变量即可。
以上就是关于大小端模式全部的内容,包括:大小端模式、汇编程序员在存储器中读写数据时,不需关注存储器的大小端顺序吗、关于单片机大小端的问题等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)