判断CPU模式是大端模式和小端模式还是小段(big

大端模式和小端模式总结
本文原创作者:. 欢迎转载,请注明出处和
什么是大端和小端
我们平常谈论一个数字时,这个数字会有高位和地位之分,写在前面的为高位,写在后面的为地位,比如0x1234,那么高位字节为0x12,地位字节为0x34,而数字在计算机里的存储有两种方式,大端和小端:
1)大端就是将高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
2)小端就是将低位字节排放在内存的低地址端,高位字节排放在内存的高地址端
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:
1)大端模式:
低地址 -----------------& 高地址
2)小端模式:
低地址 ------------------& 高地址
再举2个例子:
16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
32bit宽的数0x在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
如果把数字存在文件里,而将文件看作一个大数组的话,数组从0排到文件长度,也就是说排在前面的是低地址区,后面的是高地址区,而常见的书写方式是把高位字节写在前面,地位字节写在后面,也就是说高位字节放在低地址区,地位字节放在高地址区, 故此书写方式可以看作是大端模式。
大端模式和小端模式各自的优缺点:
1)小端模式: 提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。如果你增加数字的值,你可能在左边增加数字(高位非指数函数需要更多的数字)。 因此, 经常需要增加两位数字并移动存储器里所有Big-endian顺序的数字,把所有数向右移,这会增加计算机的工作量。不过,使用Little- Endian的存储器中不重要的字节(地位字节)可以存在它原来的位置,新的数可以存在它的右边的高位地址里。这就意味着计算机中的某些计算可以变得更加简单和快速。
2)大端模式:符号位的判定固定为第一个字节,容易判断正负。首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是 正数还是负数。你不必知道这个数值有多长,或者你也不必过一些字节来看这个数值是否含有符号位。
数组在大端小端情况下的存储
以unsigned int value = 0x为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下:
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
Little-Endian: 低地址存放低位,如下:
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
--------------
什么是大端和小端
我们平常谈论一个数字时,这个数字会有高位和地位之分,写在前面的为高位,写在后面的为地位,比如0x1234,那么高位字节为0x12,地位字节为0x34,而数字在计算机里的存储有两种方式,大端和小端:
1)大端就是将高位字节排放在内存的低地址端,低位字节排放在内存的高地址端
2)小端就是将低位字节排放在内存的低地址端,高位字节排放在内存的高地址端
举一个例子,比如数字0x12 34 56 78在内存中的表示形式为:
1)大端模式:
低地址 -----------------& 高地址
2)小端模式:
低地址 ------------------& 高地址
再举2个例子:
16bit宽的数0x1234在Little-endian模式(以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
32bit宽的数0x在Little-endian模式以及Big-endian模式)CPU内存中的存放方式(假设从地址0x4000开始存放)为:
如果把数字存在文件里,而将文件看作一个大数组的话,数组从0排到文件长度,也就是说排在前面的是低地址区,后面的是高地址区,而常见的书写方式是把高位字节写在前面,地位字节写在后面,也就是说高位字节放在低地址区,地位字节放在高地址区, 故此书写方式可以看作是大端模式。
大端模式和小端模式各自的优缺点:
1)小端模式: 提取一个,两个,四个或者更长字节数据的汇编指令以与其他所有格式相同的方式进行:首先在偏移地址为0的地方提取最低位的字节,因为地址偏移和字节数是一对一的关系,多重精度的数学函数就相对地容易写了。如果你增加数字的值,你可能在左边增加数字(高位非指数函数需要更多的数字)。 因此, 经常需要增加两位数字并移动存储器里所有Big-endian顺序的数字,把所有数向右移,这会增加计算机的工作量。不过,使用Little- Endian的存储器中不重要的字节(地位字节)可以存在它原来的位置,新的数可以存在它的右边的高位地址里。这就意味着计算机中的某些计算可以变得更加简单和快速。
2)大端模式:符号位的判定固定为第一个字节,容易判断正负。首先提取高位字节,你总是可以由看看在偏移位置为0的字节来确定这个数字是 正数还是负数。你不必知道这个数值有多长,或者你也不必过一些字节来看这个数值是否含有符号位。
数组在大端小端情况下的存储
以unsigned int value = 0x为例,分别看看在两种字节序下其存储情况,我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下:
---------------
buf[3] (0x78) -- 低位
buf[2] (0x56)
buf[1] (0x34)
buf[0] (0x12) -- 高位
---------------
Little-Endian: 低地址存放低位,如下:
---------------
buf[3] (0x12) -- 高位
buf[2] (0x34)
buf[1] (0x56)
buf[0] (0x78) -- 低位
--------------
为什么会有大小端模式之分呢?
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。
常见的字节序
一般操作系统都是小端,而通讯协议是大端的。
常见CPU的字节序
大端模式:PowerPC、IBM、Sun
小端模式:X86,DEC
ARM既可以工作在大端模式,也可以工作在小端模式
常见文件的字节序:
Adobe PS – Big Endian
BMP – Little Endian
GIF – Little Endian
JPEG – Big Endian
Unicode: windows文本文件存储为unicode格式,默认为小端模式
Unicode 大端模式文本文件: windows 文本文件也可以存储为unicode 大端模式格式。
unicode文本文件,不论是大端模式还是小端模式,存储的第一个字符都是BOM,占两个字节,BOM的unicode码是0xFEFF,存储在大端模式unicode文件里是0xFEFF,存储在小端模式unicode文件里是0xFFFE。
不同端模式的处理器进行数据传递时必须要考虑端模式的不同。如进行网络数据传递时,必须要考虑端模式的转换。在Socket接口编程中,以下几个函数用于大小端字节序的转换。
#define ntohs(n)
//16位数据类型网络字节顺序到主机字节顺序的转换
#define htons(n)
//16位数据类型主机字节顺序到网络字节顺序的转换
#define ntohl(n)
//32位数据类型网络字节顺序到主机字节顺序的转换
#define htonl(n)
//32位数据类型主机字节顺序到网络字节顺序的转换
其中互联网使用的网络字节顺序采用大端模式进行编址,而主机字节顺序根据处理器的不同而不同,如PowerPC处理器使用大端模式,而Pentuim处理器使用小端模式。
大端模式处理器的字节序到网络字节序不需要转换,此时ntohs(n)=n,ntohl = n;而小端模式处理器的字节序到网络字节必须要进行转换,此时ntohs(n) = __swab16(n),ntohl = __swab32(n)。
PowerPC处理器主导网络市场,可以说绝大多数的通信设备都使用PowerPC处理器进行协议处理和其他控制信息的处理,这也可能也是在网络上的绝大多数协议都采用大端编址方式的原因。而Pentium主导个人机市场,因此多数用于个人机的外设都采用小端模式,包括一些在网络设备中使用的PCI总线,Flash等设备,这也要求在硬件设计中注意端模式的转换。因此在有关网络协议的软件设计中,使用小端方式的处理器需要在软件中处理端模式的转变。对于通信协议来说,IP地址尤其要注意这种转换,因为主机一般都是小端模式,而网络设备一般是大端模式,故此需要转换为网络设备用的字节序,这样网络设备才可以使用ip地址进行路由。
详解大端模式和小端模式
大端模式和小端模式
感谢您的支持,我会继续努力的!
赏个5毛,支持我把//判断CPU是大端模式还是小端模式
#include &iostream&
//1、同一个内存段可以用来存放几种不同类型的成员,
//但是在每一瞬间只能存放其中的一种,而不是同时存放几种。
//换句话说,每一瞬间只有一个成员起作用,其他的成员不起作用,即不是同时都在存在和起作用。
//2、共用体变量中起作用的成员是最后一次存放的成员,在存入一个新成员后,原有成员就失去作用。
//3、共用体成员函数是从低地址向高地址存储的,与先后定义无关,如下定义
//4、共用体变量的地址和它的各成员的地址都是同一地址。(就能理解第三条了)
union union_name{
   
    
    //或者
    //
    //
    
int CPUType()
    c.a=1;
    return c.b;
int main()
    short int x=0x1122;
    int x0,x1;
    x0=((char*)&x)[0];//高字节
    x1=((char*)&x)[1];//低字节
    cout&&x0&&
    cout&&x1&&
    //若x0=17(即0x11),则是大端模式【低地址存高字节】;
    //若x0=34(即0x22),则是小端模式【低地址存低字节】.
    cout&&CPUType()&&
    //如果C.b为0的话,说明是大端模式(即是0x0001这样存储的,第一个字节为0);
    //如果C.b为1的话,说明是小端模式(即是0x0100这样存储的,第一个字节为1).
    return 0;
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:32659次
排名:千里之外
原创:14篇
转载:46篇
(3)(1)(1)(5)(1)(1)(1)(3)(1)(3)(15)(8)(8)(1)(1)(3)(5)2991人阅读
C/C++(35)
作为一个计算机相关专业的人,我们应该在计算机组成中都学习过什么叫Little endian 和Big endian。Little endian 和Big endian 是CPU 存放数据的两种不同顺序。对于整型、长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);而Little
endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放数据的低位字节到高位字节)。
例如,假设从内存地址0x0000 开始有以下数据:
0x12 0x34 0xab 0xcd
如 果我们去读取一个地址为0x0000 的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序位little-endian,则读出结果为 0xcdab3412。如果我们将0x1234abcd 写入到以0x0000 开始的内存中,则Little endian 和Big endian 模式的存放结果如下:
地址&&&&&&&&&&&&&& 0x1 0x3
big-endian&&&&&&&& 0x12&& 0x34&& 0xab&& 0xcd
little-endian&&&&& 0xcd&& 0xab 0x34&& 0x12
一般来说,x86 系列CPU 都是little-endian 的字节序,PowerPC 通常是Big endian,还有的CPU 能通过跳线来设置CPU 工作于Little endian 还是Big endian 模式。
显然,解答这个问题的方法只能是将一个字节(CHAR/BYTE 类型)的数据和一个整型数据存放于同样的内存
开始地址,通过读取整型数据,分析CHAR/BYTE 数据在整型数据的高位还是低位来判断CPU 工作于Little
endian 还是Big endian 模式。得出如下的答案:
typedef unsigned char BYTE;
int main(int argc, char* argv[])
unsigned int num,*p;
*(BYTE *)p = 0//指针类型强制转换
if(num == 0xff)
printf(&The endian of cpu is little\n&);
else //num == 0xff000000
printf(&The endian of cpu is big\n&);
除了上述方法(通过指针类型强制转换并对整型数据首字节赋值,判断该赋值赋给了高位还是低位)外,还有没
有更好的办法呢?我们知道,union 的成员本身就被存放在相同的内存空间(共享内存,正是union 发挥作用、做贡献的去处),因此,我们可以将一个CHAR/BYTE 数据和一个整型数据同时作为一个union 的成员,得出
如下答案:
int checkCPU()
return (c.b == 1);
实现同样的功能,我们来看看Linux 操作系统中相关的源代码是怎么做的:
static union { char c[4];
} endian_test = {{ 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.mylong)
Linux 的内核作者们仅仅用一个union 变量和一个简单的宏定义就实现了一大段代码同样的功能!由以上一段代码我们可以深刻领会到Linux 源代码的精妙之处!
(如果ENDIANNESS=’l’表示系统为little endian,为’b’表示big endian )。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1387365次
积分:12869
积分:12869
排名:第790名
原创:122篇
转载:15篇
评论:893条
文章:15篇
阅读:217215
(1)(1)(2)(1)(6)(2)(14)(4)(3)(7)(5)(7)(3)(2)(2)(3)(1)(5)(3)(8)(4)(5)(1)(8)(7)(5)(3)(3)(3)(3)(10)(4)(4)(3)
博客已迁移至:http://xiajunhust.github.io/

我要回帖

更多关于 大端模式和小端模式 的文章

 

随机推荐