字节序
大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。其实大部分实际开发中很少会直接和字节序打交道,唯有跨平台以及网络程序中字节序才是一个应该被考虑的问题。
就是计算机在安排数据类型存储的时候,怎样存储数据的高低位。其实这种一般和操作系统没有关系,而是和计算机的硬件架构有关,具体的说,就是CPU的设计有关,英特尔的芯片和AMD的芯片组都是使用的小端字节序(最低字节优先存储),但是有些特别的CPU就不是这样处理的。它们可能使用大端字节序(最高字节优先存储),这些在不同计算机上使用的字节序称为主机字节序。
大段与小端
Big-Endian:最高有效字节存储在较低的内存位置 (高对低,低对高)
- 0x0->0xFF 0x1->0x96
Little-Endian:最低有效字节存储在较低的内存位置 (高对高,低对低)
- 0x0->0x96 0x1->0xFF
大端模式与小端模式的实际应用范围
在我们日常使用的x86架构的计算机中,都是使用的小端模式,而网络字节序是大端模式的。这就使得在网络通信时进行字节序的转换变得极为重要。
比方说,通信双方规定了了通信头为一个4字节的魔数(Magic Number),而一方按着大端序的模式发送,一方按着小端序的模式解读,那么两方的通信就会失败。如果没有这个魔数,而在内部的数据中出现这样的问题则会更加的麻烦。
另外应明确,计算机CPU可以支持的最基本数据存储是一个字节,数据位的操作使用了特殊的寄存器。所以涉及到字节序问题的数据类型,一定是整字节的倍数,不可能是4bits,也不可是一个字节
大端模式与小端模式的优缺点
- 大端模式,由于符号位和数值的高位存在地址的低位,会优先被读到,更容易先确定数据的重要信息。
- 小端模式,在进行类型转换的时候不需要调整数据。如int强制转换到char,计算机不需要做任何调整,直接读取int的第一个字节即可。
大端和小端的检测
short a=0x0061;
if((char)a=='a')
{
//是强制转换,小端模式直接取地位数据,取出是61
qDebug()<< "小端";
}
else
{
qDebug()<<"大端";
}
联合体union和大小端
union
{
short a;
char b;
}test;
test.a=0x0061;
if(test.b=='a')
{
//这个方法利用了联合体共用内存的特性(对同一个地址截取数据比较),因此回避了强制类型转换。
qDebug()<< "小端";
}
else
{
qDebug()<<"大端";
}
Qt中大端小端的转换
union{
int a;
char b[4];
}test1,test2;
test1.a=0x61626364; //abcd
test2.a=qFromBigEndian(test1.a);
qDebug()<<test1.b[0]<<test1.b[1]<<test1.b[2]<<test1.b[3];
qDebug()<<test2.b[0]<<test2.b[1]<<test2.b[2]<<test2.b[3];
对于qFromBigEndian()函数,它会判断执行程序的主机的字节序,如果是大端模式的计算机,那么只是读取数据,不进行转换,如果是小端模式的计算机,那么则进行转换。
因此我在本机(小端模式)上的的执行结果是:
d c b a
a b c d
联合体
联合体(union)与结构体(struct)有一些相似之处。但两者有本质上的不同。
- 在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。
- 在联合体中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度
应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。
一个联合体类型必须经过定义之后, 才能使用它,才能把一个变量声明定义为该联合体类型。
定义结构体
使用typedef定义结构体
typedef用来定义新的数据类型,通常typedef与结构体的定义配合使用。使用typedef的目的使结构体的表达更加简练(所以说typedef语句并不是必须使用的)。
定义一个名字为TreeNode的结构体类型(现在并没有定义结构体变量,并不占用内存空间):
struct TreeNode
{
int Element;
struct TreeNode* LeftChild;
struct TreeNode* RightChild;
};
为结构体起一个别名Node,这时Node就等价于struct TreeNode
typedef struct TreeNode Node;
将结构体的定义和typedef语句可以连在一起写:
typedef struct TreeNode
{
int Element;
struct TreeNode* LeftChild;
struct TreeNode* RightChild;
}Node;