union与大小端

  union是C语言中的一个关键字,它的用法其实与struct很相似。
  union中的所有数据成员共用一个空间,同一时间只能存储其中的一个数据成员,并且所有的数据成员有相同的起始地址。例如:

union U
{
     double d;
     int i;
     char c;
     float f;
}u;

  我们可以使用sizeof来检测一下上面例子的大小,可以发现它的大小是其中最大长度double类型的大小,是8个字节。
  


大小端堆union类型数据的影响

首先解释一下什么是大小端?

大端(Big_endian)字数据的高字节存储在低地址中,字数据的低字节存储在高地址中。
小端(Little_endian)字数据的高字节存储在高地址中,字数据的低字节存储在低地址中。

  union型数据所占的空间等于其最大的成员所占的空间,对union型成员的存取都从相对于该联合体基地址的偏移量为0开始,也就是说对于联合体的访问,不论是哪个变量都是从union的首地址开始,所以机器大小端的不同会对union型的数据产生影响。举一个例子:

void test()
{
     union
     {
          int i;
          char a[2];
     }*p, u;
     p = &u;
     p->a[0] = 0x39;
     p->a[1] = 0x38;
     printf("%x", p->i);
}

这个程序会打印出来什么数据呢?
  通过vs2013测试,发现打印出来的是0xcccc3839。我们打开内存窗口,通过调试,可以发现内存第一行中左边是低地址,右边是高地址,而打印出来的数据的高字节存储在内存的高地址中,低字节存储在内存的低地址中,由此,也可以判断,我的电脑是小端。
至于在大端的电脑下运行结果,通过推断也可以看出来是0x3938cccc


  现在有一道题:请写一个C函数,若处理器是大端的,则返回0;若是小端的,则返回1。
这道题,我们可以通过联合体来解决。首先,我们定义一个int类型的变量,看一下他在内存中如何存储?

  通过联合体所有成员起始地址一样的特点,此时,我们取其最低位的一个字节,可以发现,如果是大端,则得到的是0,如果是小端,得到的是1。
代码如下:

int CheckSystem()
{
     union check
     {
          int i;
          char c;
     }c;
     c.i = 1;
     return c.c;
}

测试发现,结果正确:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/wei_cheng18/article/details/79856207