区别

联合体与结构体是很容易混淆的概念。

粗略一看,两者无论声明、定义还是定义对象的方式都很相似。

然而这两个东西的概念和作用实际千差万别。

首先,联合体的各个成员共用内存,并应该同时只能有一个成员得到这块内存的使用权(即对内存的读写),而结构体各个成员各自拥有内存,各自使用互不干涉。所以,某种意义上来说,联合体比结构体节约内存。
举个例子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
typedef struct
{
    int i;
    int j;
}A;
typedef union
{
  int i;
  double j;
}U;

sizeof(A)的值是8,sizeof(U)的值也是8(不是12)。
为什么sizeof(U)不是12呢?因为union中各成员共用内存,i和j的内存是同一块。而且整体内存大小以最大内存的成员的划分。即U的内存大小是double的大小,为8了。sizeof(A)大小为8,因为struct中i和j各自得到了一块内存,每人4个字节,加起来就是8了。

了解了联合体共用内存的概念,也就是明白了为何每次只能对其一个成员赋值了,因为如果对另一个赋值,会覆盖了上一个成员的值。

是的,函数的重载是在编译的时候发生,而虚函数是在运行的时候确定。其实有时候称函数的重载为静态多态性,而虚函数为动态多态性

C语言union(联合体、共用体)及应用

在结构体(变量)中,结构的各成员顺序排列存储,每个成员都有自己独立的存储位置。联合(union)变量的所有成员共享同片存储区/内存。因此联合变量每个时刻里只能保存它的某一个成员的值。

联合变量也可以在定义时直接初始化,但这个初始化只能对第一个成员进行。例如下面的描述定义了一个联合变量,并进行了初始化。

1
2
3
4
5
6
 union data
 {
     char n;
     float f;
 };
 union data u1 = {3}; //只有u1.n被初始化

union的主要特征有:

  • union中可以定义多个成员,union的大小由最大的成员的大小决定;

  • union成员共享同一块大小的内存,一次只能使用其中的一个成员;

对union某一个成员赋值,会覆盖其他成员的值(但前提是成员所占字节数相同,当成员所占字节数不同时只会覆盖相应字节上的值,比如对char成员赋值就不会把整个int成员覆盖掉,因为char只占一个字节,而int占四个字节);

  • union量的存放顺序是所有成员都从低地址开始存放的。

因此,可以用联合(union)来判断CPU的大小端(印第安序):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 int checkCPU()
 {
     union w
     {
         int a;
         char b;
     }c;

    c.a = 1;
    return ( c.b == 1 );
}

同样的道理,在Linux中给出了更加精练的实现。如果宏ENDIANNESS=’l’表示系统为little endian, 为‘b’表示big endian。

1
2
3
4
5
6
7
static union
{
    char c[4];
    unsigned long l;
}endian_test = { {'l','?','?','b'} };

#define ENDIANNESS ( (char)endian_test.l )