字节序

字节序

大于一个字节类型的数据在内存中的存放顺序(一个字节的数据当然就无需谈顺序的问题了)。其实大部分实际开发中很少会直接和字节序打交道,唯有跨平台以及网络程序中字节序才是一个应该被考虑的问题。

就是计算机在安排数据类型存储的时候,怎样存储数据的高低位。其实这种一般和操作系统没有关系,而是和计算机的硬件架构有关,具体的说,就是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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值