C语言教程:联合体

2018-10-0819:05:53编程语言入门到精通Comments3,783 views字数 2203阅读模式

像结构体一样,联合体(Union)在C语言中是一个用户定义的数据类型,用于保存不同类型的元素。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

但它并不占所有成员的内存总和。它只占最大成员的内存,它分享最大成员的内存。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

C语言教程:联合体文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

联合体优点文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

它占用较少的内存,因为它只占最大的成员的内存量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

联合体缺点文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

它将数据存储在一个成员中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

定义联合体

union关键字用于定义联合体。下面我们来看看如何在C语言中定义联合体的语法 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

union union_name   
{  
    data_type member1;  
    data_type member2;  
    .  
    .  
    data_type memeberN;  
};
C

我们来看看在C语言中定义员工联合体的例子。如下代码 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

union employee  
{   int id;  
    char name[50];  
    float salary;  
};
C

注:除了union关键字,其它均与结构体一样。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

联合体的例子

我们来看看一个简单的C语言联合示例。创建一个源文件:union-example.c,其代码实现如下 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

#include <stdio.h>  
#include <string.h>  
union employee
{
    int id;
    char name[150];
}e1;  //declaring e1 variable for union  

int main()
{
    //store first employee information  
    e1.id = 1010;
    strcpy(e1.name, "Maxsu");//copying string into char array  
                                     //printing first employee information  
    printf("employee 1 id : %d, address: %u\n", e1.id, &e1.id);
    printf("employee 1 name : %s, address: %u\n", e1.name, &e1.name);
    e1.id = 1010;
    printf("employee 1 id : %d, address: %u\n", e1.id, &e1.id);
    printf("employee 1 name : %s, address: %u\n", e1.name, &e1.name);
    return 0;
}
C

执行上面示例代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

employee 1 id : 1937269069, address: 16819328
employee 1 name : Maxsu, address: 16819328
employee 1 id : 1010, address: 16819328
employee 1 name : ?, address: 16819328
Shell

如上输出结果中可以看到,id字段的值是一个垃圾值,因为name具有大的内存大小。所以只有name才具有实际值。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

联合体完全就是共用一个内存首地址,并且各种变量名都可以同时使用,操作也是共同生效。如此多的访问内存手段,确实好用,不过这些“手段”之间却没法互相屏蔽——就好像数组+下标和指针+偏移一样。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

由于联合体中的所有成员是共享一段内存的,因此每个成员的存放首地址相对于于联合体变量的基地址的偏移量为0,即所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。对于这句“对齐方式要适合其中所有的成员”是指其必须符合所有成员的自身对齐方式。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

下面举例说明:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

union U
{
    char s[9];
    int n;
    double d;
};
C

s占9字节,n占4字节,d占8字节,因此其至少需9字节的空间。然而其实际大小并不是9,用运算符sizeof测试其大小为16.这是因为这里存在字节对齐的问题,9既不能被4整除,也不能被8整除。因此补充字节到16,这样就符合所有成员的自身对齐了。从这里可以看出联合体所占的空间不仅取决于最宽成员,还跟所有成员有关系,即其大小必须满足两个条件:1)大小足够容纳最宽的成员;2)大小能被其包含的所有基本数据类型的大小所整除。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

测试程序,创建一个源文件:union-test.c,其代码实现如下 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

#include <stdio.h>  
#include <string.h>  

union U1
{
    char s[9];
    int n;
    double d;
}u1;

union U2
{
    char s[5];
    int n;
    double d;
}u2;

int main()
{
    printf("%d\n", sizeof(u1));
    printf("%d\n", sizeof(u2));
    printf("0x%x\n", &u1);
    printf("0x%x\n", &u1.s);
    printf("0x%x\n", &u1.n);
    printf("0x%x\n", &u1.d);
    u1.n = 1;
    printf("%d\n", u1.s[0]);
    printf("%lf\n", u1.d);
    unsigned char *p = (unsigned char *)&u1;
    printf("%d\n", *p);
    printf("%d\n", *(p + 1));
    printf("%d\n", *(p + 2));
    printf("%d\n", *(p + 3));
    printf("%d\n", *(p + 4));
    printf("%d\n", *(p + 5));
    printf("%d\n", *(p + 6));
    printf("%d\n", *(p + 7));
    return 0;
}
C

执行上面测试代码,得到以下结果 -文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html

16
8
0xeca5a0
0xeca5a0
0xeca5a0
0xeca5a0
1
0.000000
1
0
0
0
0
0
0
0
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/6462.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/6462.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定