1. 什么是大小端模式?区别? (小端存储模式和大端存储模式)
如数字0x1234,低字节位是0x34,高字节位是0x12。 假设从地址0x4000处开始存放
内存地址 小端模式(little-endian) 大端模式(big-endian)
0x4000 0x34 0x12
0x4001 0x12 0x34
总:Little-Endian,数据类型中的高位数据存放于高地址部分,底位数据存放于底地址部分。
Big-Endina, 数据类型中的高位数据存放于内存的地址部分,低位数据存放于内存的低地址部分!
采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,
而Big-endian模式对操作数的存放方式是从高字节到低字节。
计算机世界中借用大小端指“多字节数据类型中的字节顺序”。
注:不管是大端还是小端,cpu总是从内存的低位到高位读取数据
每一个内存单元都是8位,对应1字节!
2. 各自的优缺点?
没有谁优谁劣之分,各自的优势便是对方的劣势!
大端模式:符号位在第一字节,容易判断正负!
小端模式:???
3. 大小端之分产生的原因?
大小端模式是字节序不同......(待补充)
计算机世界中借用大小端指“多字节数据类型中的字节顺序”。
4. 数组在大小端模式下的存储
以unsigned int value = 0x12345678为例,分别看看在两种字节序下其存储情况,
我们可以用unsigned char buf[4]来表示value:
Big-Endian: 低地址存放高位,如下: Little-Endian: 低地址存放低位,如下:
高地址
---------------
buf[3] (0x78) -- 低位 buf[3] (0x12) -- 高位
buf[2] (0x56) buf[2] (0x34)
buf[1] (0x34) buf[2] (0x34)
buf[0] (0x12) -- 高位 buf[0] (0x78) -- 低位
低地址---------------
5. 大小端模式的具体应用
比如某协议规定了数据按大端模式(Big-Endian)组织,而实现协议的系统是小端模式(Little-Endian), 那么协议的实现代码就需要对输入数据从(Big-Endian)转换为(Little-Endian),再进行运算, 输出数据也要从(Little-Endian)转换为(Big-Endian)。
Linux 系统为大小端模式的转换提供了 4 个函数,输入 man byteorder 命令可得函数原型
6. 判断本机大小端模式的方法
思路1:如一个unsigned int a = 0x 1234; 把a转换成unsigned char (单字节),unsigned char *b = (unsigned char *)&a;
因为b(字符串首地址,第一个地址)表示整个字符串,所以只需判断b[0] 是否等于0x34就知是否是小端模式!
#define U16 unsigned short;
#define U8 unsigned char;
int IsLittleEndian()
{
U16 i = 0x1234;
U8* p = (U8*)&i;
if( p[0] == 0x34 && p[1] == 0x12 )return 1;//系统是Little-Endian
if( p[0] == 0x12 && p[1] == 0x34 )return 0;//系统是Big-Endian
return 0;
}
方法2:读写联合体union的存放顺序是所有成员都从低地址开始存放,利用该特性,可轻松地获得CPU对内存采用Little-endian还是Big-endian模式
typedef enum {false, true} bool;
bool IsBigEndian()
{
union NUM
{
int a;
char b;
}num;
num.a = 0x1234;
if( num.b == 0x12 )
return true;
return false; //return (num.b == 0x12);
}
7. 大小端模式之间的转换!
(待补充)
8.常见的字节序
一般操作系统都是小端,而通讯协议是大端的。
8.1 常见CPU的字节序
Big Endian : PowerPC、IBM、Sun
Little Endian : x86、DEC
ARM既可以工作在大端模式,也可以工作在小端模式。
8.2 常见文件的字节序
Adobe PS – Big Endian
BMP – Little Endian
GIF – Little Endian
JPEG – Big Endian
Java和所有的网络通讯协议都是使用Big-Endian的编码。
补:十六进制数,以0x开始,这里的0是数字0,不是字母O!
我们为什么常用十六进制数呢?计算机中所有的数据都是以二进制的形式存储的,有时用二进制我们可以直观的解决问题。
但是二进制表示数太长,如int a = 3; 用二进制表示 0000000 00000000 00000000 00000011 面对这么长的数进行思考或操作,没有人会喜欢。
因此,C,C++ 没有提供在代码直接写二进制数的方法。用16进制或8进制可以解决这个问题。