从大端小端,到联合体与结构体

问题引出: 计算机大端小端之争。
1)Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。
2) Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
数字0x12345678 在大端小端的存储方式 

1)大端模式:

低地址 -----------------> 高地址
0x12  |  0x34  |  0x56  |  0x78

2)小端模式:

低地址 ------------------> 高地址
0x78  |  0x56  |  0x34  |  0x12

内存地址 小端模式存放内容 大端模式存放内容
0x4000 0x78 0x12
0x4001 0x56 0x34
0x4002 0x34 0x56
0x4003 0x12 0x78
大端小端的Pro and con
小端: 强制类型转化时候比较方便; 大端判断符号类型比较方便。

实际中: 
操作系统使用小端,网络程序使用大端;

硬件
Big endian: PowerPC, Sun, IBM;
Little endian: Intel, DEC
ARM既可以大端也可以小端。

如何判断是大端还是小端
void Test_1()
{
    unsigned int a = 0x1234; /*unsigned int to check if 0x 12 34 or 0x 34 12*/
    char* b = (char *) &a;   /*取unsigned int的地址,然后将它强制转化为char型*/

    if(b == 0x12)  /*如果是0x 12 34大端,强制转化了则b 为0x12*/
    {
        printf("Big endian\n");
    }else  /*如果是0x 34 12小端,强制转化了则b 为0x34*/
    {
        printf("Little endian and %x\n", *b);
    }
}

其他办法,因为C语言的联合的各个成员会共享一块内存,所以是否可以通过联合体来判断。
typedef unsigned char BYTE;
void Test_2()
{
    unsigned int num = 0; /*num = 0x 00 00 00 00*/
    unsigned int *p = #

    *(BYTE *)p = 0xff; /*to check where the system put the 0x 00 00 00 ff or 0x ff 00 00 00*/

    if(num == 0xff) /* 0x 00 00 00 ff*/
    {
        printf("This endian of cpu is little\n");
    }else           /* 0x ff 00 00 00*/
    {
        printf("This endian of cpu is big\n");
    }
}

看看linux 如何判断大端小端的
static union
{
    char c[4];
    unsigned long l;

}linuxEndianTest = {{'l','?','?','b'}};
#define LINUXENDIAN ((char) linuxEndianTest.l)
void Test_4()
{
    printf("%c", LINUXENDIAN);

}

实际的应用:
在单片机编程中,联合体和位域结合,可以实现对LED的控制
有时候既想操作整个字节 显示一个数,也想控制某位闪烁。
定义如下的联合体
typedef union uFLG{
    uint8 Flg ;                   //定义整型,可以一次性操作
    struct FLAG{               //位域定义,可以一次性操作一个位
        uint8   Flg1   : 1;
        uint8   Flg2   : 1;
        uint8   Flg3   : 1;
        uint8   Flg4   : 1;
        uint8   Flg5   : 1;
        uint8   Flg6   : 1;
        uint8   Flg7   : 1;
        uint8   Flg8   : 1;
    }tFlg;  
}uFlg;

//-------uF1-------------------
#define uFg1                uF1.Flg       //可以操作位
#define F_LED1          uF1.tFlg.Flg1
#define F_LED2          uF1.tFlg.Flg2
#define F_LED3          uF1.tFlg.Flg3

uFg1 = 0x88;
F_LED1 = 0x01;

网络协议中,不同的报文类型PackageType,不同的报文内容PackageContent,使用同一个结构表示。
typedef union tagPackageContent
  {
           PackageContent1 content1;
           PackageContent2 content2;
           PackageContent3 content3;
           PackageContent3 content3;
  };

typedef struct PackageStructure {
     Byte type;
     tagPackageContent content;
}



你可能感兴趣的:(Tech)