精华内容
下载资源
问答
  • union,中文名“联合体、共用体”,在某种程度上类似结构体struct一种数据结构共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。 但在“联合”中, 各成员共享一段内存空间, 一个联合变量长度...

    union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。

    但在“联合”中, 各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度 。一个联合体类型必须经过定义之后, 才能使用它,才能把一个变量声明定义为该联合体类型。

    当定义结构对象时,如果没有显式地初始化它们,则会采用一般初始化规则:如果该结构对象属于动态存储类型,那么其成员具有不确定的初始值。

    另一方面,如果结构对象具有静态存储周期,那么其非指针成员初始值是 0,其指针成员初始值是空指针。

    不同于结构成员——它们在结构中都具有单独的内存位置,联合成员则共享同一个内存位置。也就是说,联合中的所有成员都是从相同的内存地址开始。因此,可以定义一个拥有许多成员的联合,但是同一时刻只能有一个成员允许含有一个值。联合让程序员可以方便地通过不同方式使用同一个内存位置。

    一、定义联合(union)
    联合的定义方式与结构是一样的,只是把关键字 struct 改成 union:

    1
    union [标签名称]{成员声明列表};
    下面的例子定义了一个名为Data的联合类型,它有 3 个成员:i、x 和 str:

    1
    union Data { int i;double x;char str [16];};
    这种类型的对象可以存储一个整数、一个浮点数或一个短字符串。

    例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    union StateMachine
     
    {
     
      char character;
     
      int number;
     
      char *str;
     
      double exp;
     
    };
    一个union 只配置一个足够大的空间以来容纳最大长度的数据成员,以上例而言,最大长度是double 型态,所以StateMachine 的空间大小就是double 数据类型的大小。

    在C++里,union 的成员默认属性页为public。union 主要用来压缩空间。如果一些数据不可能在同一时间同时被用到,则可以使用union。

    二、初始化联合(union)
    与结构类似,通过初始化列表(initialization list)来初始化联合对象。但是,对联合来说,列表只有一个初始化器(initializer)。

    与结构一样,C99 允许在初始化器中使用成员指示符来指示哪个成员被初始化。而且,如果初始化器没有成员指示符,那么就与联合内的第一个成员关联。具有自动存储类的联合对象也可以使用已有的同类型对象来初始化。下面是一些初始化例子:

    1
    2
    3
    4
    5
    6
    7
    union Data var1={77},
     
    var2={.str="Mary"},
     
    var3=var1,
     
    myData[100]={{.x=0.5},{1},var2};
    数组 myData 中的元素如果没有指定初始化器,会被隐式地初始化为 0 值。

    三、联合体变量的声明
    联合变量的说明和结构变量的声明方式相同, 也有三种形式:

     第一种 , 先定义联合体类型,再声明联合体变量 ;

     第二种 ,定义联合体类型的同时声明联合体变量;

     第三种 ,直接声明联合体(以匿名的形式定义联合体类型)。

    以perdata类型为例,说明如下:

    第一种, 先定义联合体类型,再声明联合体变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    union  perdata
     
    {
     
      int class;
     
      char officae[10];
     
    };
     
    union  perdata a,b; /*说明a,b为perdata类型*/
    第二种, 定义联合体类型的同时声明联合体变量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    union perdata
     
    {
     
    int class;
     
    char office[10];
     
    } a , b ;
    第三种, 直接声明联合体(以匿名的形式定义联合体类型):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    union
     
    {
     
    int class;
     
    char office[10];
     
    }a,b
    经说明后的a,b变量均为perdata类型。a,b变量的长度应等于 perdata 的成员中最长的长度, 即等于office数组的长度,共10个字节。对a,b变量如赋予整型值时,只使用了2个字节,而赋予字符数组时,可用10个字节。

    四、联合体变量的赋值和使用
    对联合体变量的赋值,使用都只能是对变量的成员进行。

    联合变量的成员表示为:  联合变量名 . 成员名 

    例如,a被说明为perdata类型的变量之后,可使用 a.class,a.office

    不允许只用联合变量名作赋值或其它操作。 也不允许对联合变量作初始化赋值,赋值只能在程序中进行。

    一个联合体变量, 每次只能赋予一个成员值。一个联合变量的值就是联合变员的某一个成员值。

    展开全文
  • union,中文名“联合体、共用体”,在某种程度上类似结构体struct一种数据结构共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。 但在“联合”中,各成员共享一段内存空间, 一个联合变量长度...

    union,中文名“联合体、共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以包含很多种数据类型和变量。

    但在“联合”中, 各成员共享一段内存空间, 一个联合变量的长度等于各成员中最长的长度 。一个联合体类型必须经过定义之后, 才能使用它,才能把一个变量声明定义为该联合体类型。

    当定义结构对象时,如果没有显式地初始化它们,则会采用一般初始化规则:如果该结构对象属于动态存储类型,那么其成员具有不确定的初始值。

    另一方面,如果结构对象具有静态存储周期,那么其非指针成员初始值是 0,其指针成员初始值是空指针。

    不同于结构成员——它们在结构中都具有单独的内存位置,联合成员则共享同一个内存位置。也就是说,联合中的所有成员都是从相同的内存地址开始。因此,可以定义一个拥有许多成员的联合,但是同一时刻只能有一个成员允许含有一个值。联合让程序员可以方便地通过不同方式使用同一个内存位置。

     

    一、定义联合(union)

    联合的定义方式与结构是一样的,只是把关键字 struct 改成 union:

    union [标签名称]{成员声明列表};

    下面的例子定义了一个名为Data的联合类型,它有 3 个成员:i、x 和 str:

    union Data { int i;double x;char str [16];};

    这种类型的对象可以存储一个整数、一个浮点数或一个短字符串。

    例如:

    union StateMachine 

       char character; 

       int number; 

       char *str; 

       double exp; 

    }; 

    一个union 只配置一个足够大的空间以来容纳最大长度的数据成员,以上例而言,最大长度是double 型态,所以StateMachine 的空间大小就是double 数据类型的大小。 

    在C++里,union 的成员默认属性页为public。union 主要用来压缩空间。如果一些数据不可能在同一时间同时被用到,则可以使用union。 

    二、初始化联合(union)

    与结构类似,通过初始化列表(initialization list)来初始化联合对象。但是,对联合来说,列表只有一个初始化器(initializer)。

    与结构一样,C99 允许在初始化器中使用成员指示符来指示哪个成员被初始化。而且,如果初始化器没有成员指示符,那么就与联合内的第一个成员关联。具有自动存储类的联合对象也可以使用已有的同类型对象来初始化。下面是一些初始化例子:

    union Data var1={77},

    var2={.str="Mary"},

    var3=var1,

    myData[100]={{.x=0.5},{1},var2};

    数组 myData 中的元素如果没有指定初始化器,会被隐式地初始化为 0 值。

    三、联合体变量的声明

     联合变量的说明和结构变量的声明方式相同, 也有三种形式:

     第一种 , 先定义联合体类型,再声明联合体变量 ; 

     第二种 ,定义联合体类型的同时声明联合体变量;

     第三种 ,直接声明联合体(以匿名的形式定义联合体类型)。

    以perdata类型为例,说明如下: 

    第一种, 先定义联合体类型,再声明联合体变量

    union   perdata

    {

       int class;

       char officae[10];

    };

    union   perdata  a,b;  /*说明a,b为perdata类型*/

    第二种, 定义联合体类型的同时声明联合体变量:

    union  perdata

    int class;

    char office[10]; 

    } a , b ;

    第三种, 直接声明联合体(以匿名的形式定义联合体类型):

    union

    int class;

    char office[10]; 

    }a,b 

    经说明后的a,b变量均为perdata类型。a,b变量的长度应等于 perdata 的成员中最长的长度, 即等于office数组的长度,共10个字节。对a,b变量如赋予整型值时,只使用了2个字节,而赋予字符数组时,可用10个字节。

    四、联合体变量的赋值和使用

     对联合体变量的赋值,使用都只能是对变量的成员进行。 

    联合变量的成员表示为:  联合变量名 . 成员名  

    例如,a被说明为perdata类型的变量之后,可使用 a.class,a.office 

    不允许只用联合变量名作赋值或其它操作。 也不允许对联合变量作初始化赋值,赋值只能在程序中进行。

    一个联合体变量, 每次只能赋予一个成员值。一个联合变量的值就是联合变员的某一个成员值。

    五、struct和union和区别

    1.结构和联合都是由多个不同的数据类型成员组成的,但是在任一时刻联合只存放一个被选中的成员,而结构的所有成员都存在。

    2。对于联合的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对结构的不同成员赋值是会不影响的。

    对联合变量的赋值,都只能对变量的成员进行,一个联合变量每次只能赋值给一个成员,一个联合变量的值就是当前联合变量的某一个成员值。

    应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。

     

    如果你想更好的提升你的编程能力,学好C语言C++编程!弯道超车,快人一步!

    C语言C++学习企鹅圈子】,分享(源码、项目实战视频、项目笔记,基础入门教程)

    欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

    编程学习书籍:

     

    编程学习视频:

     

    展开全文
  • C语言程序设计与数据结构 2共用体变量之间赋值 新ANSI C标准允许两个类型相同的共用体变量之间进行赋值操作这与结构体变量之间作为整体进行赋值操作是一样 例如有两个共用体变量u1和u2且对u1进行了初始化则...
  • 目录 结构体 1、定义与声明 ...3、共用体的大小与内存对齐 位段 1、定义与声明 2、性质 3、大小 结构体 1、定义与声明 在C语言中,结构体(struct)指是一种数据结构,是C语言中聚合数据类型(a...

    目录

    结构体

    1、定义与声明

    2、结构体变量的初始化

    3、访问结构体成员

    4、结构体的输出

    4、typedef关键字

    5、结构体的大小与内存对齐

    共用体

    1、定义与规则

    2、访问共用体成员

    3、共用体的大小与内存对齐

    位段

    1、定义与声明

    2、性质

    3、大小


    结构体

    1、定义与声明

    在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问。

    定义:

    结构体的定义如下所示

    struct tag { 
        member-list
        member-list 
        member-list  
        ...
    } variable-list ;

    tag 是结构体标签。

    member-list 是标准的变量定义,比如 int i; 或者 float f,或者其他有效的变量定义。

    variable-list 结构变量,定义在结构的末尾,最后一个分号之前,可以指定一个或多个结构变量

    在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。以下为实例:

    声明1:
    
    /* 此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
    同时又声明了结构体变量s1,这个结构体并没有标明其标签 */
    struct 
    {
        int a;
        char b;
        double c;
    } s1;
    
    
    声明2:
    /* 此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
    结构体的标签被命名为SIMPLE,没有声明变量 */
    struct SIMPLE
    {
        int a;
        char b;
        double c;
    };
    /*用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
      struct SIMPLE t1, t2[20], *t3;
    上述两个声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的,如果令 t3=&s1,则是非法的。*/
    
    
    声明3:
    //也可以用typedef创建新类型
    typedef struct AA
    {
        int a;
        char b;
        double c; 
    } Simple2;
    //现在可以用AA或者Simple2作为类型声明新的结构体变量
    AA u1, u2[20], *u3;
    Simple2 u4, u5[20], *u6;

    注意在当前结构体内,不能自引用,实例如下:

    struct A
     {
    	 char a;
    	 int b;
    	// struct A bb;   //错误写法,在当前结构体内,不能自引用
    	 struct A *p;   //next指针
     }Aa;

    结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。 

    //此结构体的声明包含了其他的结构体
    struct COMPLEX
    {
        char string[100];
        struct SIMPLE a;
    };
     
    //此结构体的声明包含了指向自己类型的指针
    struct NODE
    {
        char string[100];
        struct NODE *next_node;
    };

    如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明

    struct B;    //对结构体B进行不完整声明
     
    //结构体A中包含指向结构体B的指针
    struct A
    {
        struct B *partner;
        //other members;
    };
     
    //结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明
    struct B
    {
        struct A *partner;
        //other members;
    };

    2、结构体变量的初始化

    实例: 

     struct Student    //struct只是一个关键字
    {
    	char name[10];
    	int age;
    	char sex[5];
    }st={"z",18,"man"};  //聚合类型,初始化只有一次机会

    注意:结构体是聚合数据类型,初始化只有一次机会,且在结构体定义内部不能给成员赋值

    3、访问结构体成员

    访问结构的成员,可以使用成员访问运算符(.)

    #include<stdio.h>
    struct Student
     {
    	 char name[10];
    	 int Age;
     }pupil = {"zhao",18};
    
    int main()
    {
    	Student *p = &pupil;   // 定义结构体指针,指向结构体变量pupil
        printf("%s,%d\n",pupil.name,pupil.Age);  // 使用 “ 结构体变量名.成员名 ” 访问
        printf("%s,%d\n",p->name,p->Age);  // 使用 “ 结构体指针 -> 成员名 ” 访问
    }
    #include<stdio.h>
    struct Student
     {
    	 char name[10];
    	 int Age;
    }pupil;
    
    int main()
    {
    	struct Student stu ={"zhao",18};
    	printf("%s,%d\n",stu.name,stu.Age);
    }
    
    #include<stdio.h>
    typedef struct Student
     {
    	 char name[10];
    	 int Age;
    }pupil;  // 相当于Student的别名
    
    int main()
    {
    	pupil stu = {"zhao",18}; // 若没有typedef,则必须使用 struct Student stu
        printf("%s,%d\n",stu.name,stu.Age);  // 使用 “ 结构体变量名.成员名 ” 访问
    }
    

    4、结构体的输出

    #include<stdio.h>
     typedef struct Student
     {
    	 char name[10];
    	 int Age;
     }pupil;
    
     void show(pupil *p,int len)   
     {
    	 for(int i =0;i<len;i++)
    	 {
    		 printf("%s,%d\n",p[i].name,p[i].Age);
    	 }
    	 printf("\n");
     }
    
    int main()
    {
    	pupil arr[3]={{"cc",18},{"dd",19},{"ee",20}};
    	int len = sizeof(arr)/sizeof(arr[0]);
    	show(arr,len);
    }

    运行结果:

    嵌套结构体的输出

    #include<stdio.h>
    typedef struct A
     {
    	 char a;
    	 int b;
     }Aa;
     
     typedef struct B
     {
    	 int i;    
    	 struct A Aaa;
    	 struct A *P;
     }Bb;
    
    int main()
    {
    	Aa s1 = {'a',18};
    	Bb s2;
    	s2.Aaa = s1;    // Aaa相当于Aa 
    	s2.P = &s1;  
    	printf("%c,%d\n",s1.a,s1.b);
    	printf("%c,%d\n",s2.Aaa.a,s2.Aaa.b);
    	printf("%c,%d\n",s2.P->a,s2.P->b);
    }

    运行结果:

    4、typedef关键字

    typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异。它本身是一种存储类的关键字,与auto、extern、mutable、static、register等关键字不能出现在同一个表达式中。

    int (*P)[3];         //此时P是数组指针类型的变量变量
    typedef int (*P)[3]; //此时P代表数组指针类型,用它可以定义一个数组指针类型的变量
    
    int (*Pfun)(int,int); //此时Pfun是函数指针类型的变量
    typedef int (*Pfun)(int,int); //此时Pfun代表Pfun是函数指针类型,它可以定义一个函数指针类型的变量
    
    unsigned int Unint;   //此时Unint是无符号整型变量
    typedef unsigned int Unint;  //此时Unint代表是无符号整型类型,它可以定义一个无符号整型的变量
    
    int INT;  //此时INT是有符号整型变量
    typedef int INT;  //此时Unint代表是有符号整型类型,它可以定义一个有符号整型的变量
     
    int A[10];  //此时A代表一个整形数组名
    typedef int A[10];  //此时A代表一个整形数组类型,它可以定义一个整形数组

    typedef与const

    int i = 10;
    int i2 = 100;
    
    const int *p3 = &i;  //const修饰*p3,*p3不可变
    *p3 = 1000;
    p3 = &i2; 
    	
    int* const p4 = &i;  //const修饰指针p4,p4不可变
    *p4 = 1000;
    p4 = &i2; 
    
    
    typedef int *PP;   //由int*类型变量提升为int*类型
    
    const PP p1 = &i;   // const修饰指针p1,p1不可变
    *p1 = 100;  
    p1 = &i2; 
    
    PP const p2 = &i;    // const修饰指针p2,p2不可变
    *p2 = 100;
    p2 = &i2;

    typedef与define 

    typedef int *PP;   // PP a,b  a,b都是int*类型
    #define P int*;    //  p a,b  a是int*类型  b是int类型

    typedef与结构体 

    可以对结构体使用 typedef 来定义一个新的数据类型名字,然后使用它来直接定义结构变量

    #include<stdio.h>
    typedef struct Student
     {
    	 char name[10];
    	 int Age;
    }pupil;  // pupil此时不再是变量,而是类型名,相当于Student的别名
    
    int main()
    {
        //使用pupil直接定义变量,若没有typedef,则必须使用 struct Student stu
        pupil stu = {"zhao",18}; 
        printf("%s,%d\n",stu.name,stu.Age);  
    }
    

    5、结构体的大小与内存对齐

    C与C++ 区别 :

    C:空结构体 ,大小不确定,报错;

    C++: 空结构体,大小1个字节

    结构体的大小不是结构体元素单纯相加就行的,因为我们主流的计算机使用的都是32bit字长的CPU,对这类型的CPU取4个字节的数要比取一个字节要高效,也更方便。所以在结构体中每个成员的首地址都是4的整数倍的话,取数据元素时就会相对更高效,这就是内存对齐的由来。

    每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

    结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则:

    1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    2. 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
    3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

    对于以上规则的说明如下:

    第一条:编译器在给结构体开辟空间时,首先找到结构体中最宽的基本数据类型,然后寻找内存地址能被该基本数据类型所整除的位置,作为结构体的首地址。将这个最宽的基本数据类型的大小作为上面介绍的对齐模数

    第二条:为结构体的一个成员开辟空间之前,编译器首先检查预开辟空间的首地址相对于结构体首地址的偏移是否是本成员大小的整数倍,若是,则存放本成员,反之,则在本成员和上一个成员之间填充一定的字节,以达到整数倍的要求,也就是将预开辟空间的首地址后移几个字节。

    第三条:结构体总大小是包括填充字节,最后一个成员满足上面两条以外,还必须满足第三条,否则就必须在最后填充几个字节以达到本条要求。

    struct AA 
    { 
    	char a;   // 1 + 3
    	short b; //  4
    	int c;   // 4
    	double d;  // 8
    };  //16
     
    struct A
    {
    	char a;   // 1 + 3   [0,1,2,3] (1,2,3浪费)
    	int b;    // 4  [4,5,6,7]
    }; //[0-7]  大小为8,向前对齐
    
    struct A1
    {
    	char a;   //1
    	char c;   //1 
    	int b;    //4  
    }s; // 大小为8
    
    struct B
    {
    	char a;   //1 + 1  [0,1]
    	short b;  //2  [2,3]
    	int c;    // 4  [4,5,6,7]
    }; //   [0-7]大小为8,向前对齐
    
    struct C
    {
    	char a;   // 1 + 3  [0,1,2,3]
    	int b;    // 4  [4,5,6,7]
    	short c;  // 2 + 6  [8-15]
    	double d; // 8  [16-23]
    }; // [0-23]大小为24,向前对齐
    
    struct D
    {
    	char a;   // 1 [0]
    	char b;   // 1 [1]
    	short c;  // 2 [2,3]
    	int d;    // 4 [4,5,6,7]
    }; // [0-7]大小为8,向前对齐
    
    struct E
    {
        char a;   // 1 + 1 [0,1]
        short c;   // 2 [2,3]
        char b;  // 1 + 3 [4,5,6,7]
    	int d;  // 4 [8,9,10,11]
    }; // [0-11]大小为12,向前对齐
    
    struct F
    {
        int a;  // 4 [0,1,2,3]
        char c; // 1 + 3  [4,5,6,7]
    }; //[0-7]大小为8,向后对齐,一般只有两个数据成员
    
    struct G
    {
        char ch[17];  //17 + 3  20能被4整除
        int i; // 4
        float f; //4
    }su;  // 大小为28
    
    struct H
    {
        char  a;  //1 +1
        short b;   //2
        char  c;  //1 +3
        int   d;  //4
        char  e[3]; //3 +1
    };   // 大小为16
    

    共用体

    1、定义与规则

    共用体是一种特殊的数据类型,允许在相同的内存位置存储不同的数据类型。可定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。

    联合体中的所有成员是共享一段内存,因此每个成员的存放首地址相对于联合体变量的基地址的偏移量为 0,即 所有成员的首地址都是一样的。为了使得所有成员能够共享一段内存,因此该空间必须足够容纳这些成员中最宽的成员。 

    使用 union 语句定义一个共用体类型,方式与定义结构体类似。union 语句定义了一个新的数据类型,带有多个成员。union 语句的格式如下:

    union [union tag]
    {
       member definition;
       member definition;
       ...
       member definition;
    } [one or more union variables];

    union tag 是可选的,每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在共用体定义的末尾,最后一个分号之前,可以指定一个或多个共用体变量,这是可选的。下面定义一个名为 Data 的共用体类型,有三个成员 i、f 和 str: 

    union Data
    {
       int i;
       float f;
       char  str[20];
    } data;

    共用体占用的内存应足够存储共用体中最大的成员。例如,在上面的实例中,Data 将占用 20 个字节的内存空间,因为在各个成员中,字符串所占用的空间是最大的。 

    规则:

    1. 同一内存在每一瞬时只能保存一个成员
    2. 起作用的成员是最后一次赋值的成员
    3. 只能对联合体/共用体的第一个成员进行初始化,不然后面的赋值会覆盖掉第一个的值
    4. 共用的体变量的地址和他的各成员地址都是同一个地址,就是首地址
    5. 共用体结构可以互相嵌套

    2、访问共用体成员

    为了访问共用体的成员,使用成员访问运算符(.),使用 union 关键字来定义共用体类型的变量。

    #include <stdio.h>
    #include <string.h>
     
    union Data
    {
       int i;
       float f;
       char  str[20];
    };
     
    int main( )
    {
       union Data data;        
     
       data.i = 10;
       data.f = 220.5;
       strcpy( data.str, "C Programming");
     
       printf( "data.i : %d\n", data.i);
       printf( "data.f : %f\n", data.f);
       printf( "data.str : %s\n", data.str);
     
       return 0;
    }

    运行结果:

    由运行结果可以得出:共用体的 i 和 f 成员的值不是所期望的,因为最后赋给变量的值占用了内存位置变量的赋值以最后一次赋值为准,这也是 str 成员能够完好输出的原因。

    修改上例:在同一时间只使用一个变量,这也是使用共用体的主要目的:

    #include <stdio.h>
    #include <string.h>
     
    union Data
    {
       int i;
       float f;
       char  str[20];
    };
     
    int main( )
    {
       union Data data;        
     
       data.i = 10;
       printf( "data.i : %d\n", data.i);
       
       data.f = 220.5;
       printf( "data.f : %f\n", data.f);
       
       strcpy( data.str, "C Programming");
       printf( "data.str : %s\n", data.str);
     
       return 0;
    }

    运行结果:

    此时,所有的成员都能完好输出,因为同一时间只用到一个成员。

    3、共用体的大小与内存对齐

    union sample
    {
    	short i; //2
    	char ch; //1
    	float f; //4
    	union MyUnion
    	{
    		char ch;
    	};
    }s;  // 大小为4
    
    
    union uu
    {
    	int a;  //4
    	short b;  //2
    	int c; //4
    }s1; // 大小为4
    
    
    union sample2
    {
    	char ch[10]; 
    	int i; //4
    	float f; //4
    }s2;  //大小为12
    
    
    union u1 
    { 
    	char arr[4]; //4
    	int n; // 4
    	double d; // 8
    };  //大小为8
    
    
    union u2 
    { 
    	char arr[10];  // 10 + 6 满足能被8整除
    	int n; //4
    	double d;  //8
    };  //大小为16

    位段

    1、定义与声明

    C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据

    信息的存取一般以字节单位。实际上,有时存储一个信息不必用一个或多个字节,例如,“真”或“假”用0或1表示,只需1位即可。在计算机用于过程控制、参数检测或数据通信领域时,控制信息往往只占一个字节中的一个或几个二进制位,常常在一个字节中放几个信息。

    例:

    在C语言中,位段的声明和结构体(struct)类似,但它的成员是一个或多个位的字段,这些不同长度的字段实际储存在一个或多个整型变量中。在声明时,位段成员必须是整形或枚举类型(通常是无符号类型,且在成员名的后面是一个冒号和一个整数,整数规定了成员所占用的位数。位域不能是静态类型不能使用&对位域做取地址运算,因此不存在位域的指针,编译器通常不支持位域的引用(reference)。以下程序则展示了一个位段的声明:

    struct CHAR
    {
        unsigned int ch   : 8;    //8位
        unsigned int font : 6;    //6位
        unsigned int size : 18;   //18位
    };
    struct CHAR ch1;

    以下程序展示了一个结构体的声明:

    struct CHAR2
    {
        unsigned char ch;    //8位
        unsigned char font;  //8位
        unsigned int  size;  //32位
    };
    struct CHAR2 ch2;

    第一个声明应用了位段声明。它可以处理256个不同的字符(8位),64种不同字体(6位),以及最多262144个单位的长度(18位)。这样,在ch1这个字段对象中,一共才占据了32位的空间。而第二个程序利用结构体进行声明,可以看出,处理相同的数据,CHAR2类型占用了48位空间,如果考虑边界对齐并把要求最严格的int类型最先声明进行优化,那么CHAR2类型则要占据64位的空间。

    注意位数:

    #include<stdio.h>
    typedef struct Demo 
    {  
        unsigned int a : 1;  
        unsigned int b : 2;  
        unsigned int c : 3; 
    }demo; 
     
    int main() 
    {  
        demo d;  
        d.a = 1230; 
        printf("%d\n",d.a);  //0 因为只能放低位的一个二进制数字 
        d.a = 1233; 
        printf("%d\n",d.a);  //1 因为只能放低位的一个二进制数字 
        return 0;
    }

    注意有符号和无符号:

    #include<stdio.h>
    typedef struct Demo 
    {  
    	int a : 1;  
    	unsigned int b : 2;  
    	unsigned int c : 3; 
    }demo; 
     
    int main() 
    {  
    	demo d;  
    	d.a = 1;  //  a存储1位有符号整形数据   二进制(01)最低位 1  输出 -1
    	printf("%d\n",d.a); // -1  
    
    	d.a = 2;  //  a存储1位有符号整形数据   二进制(10)最低位 0  输出 0
    	printf("%d\n",d.a); // 0  
    
    	d.a = 3;  //  a存储1位有符号整形数据   二进制(11)最低位 1  输出 -1
    	printf("%d\n",d.a); // 0 
    
    
    	d.b = 7;
    	printf("%d\n",d.b); // 3  b存储两位无符号整形数据,0111输出最低位(11)输出 3
    
    	d.b = 10;
    	printf("%d\n",d.b); // 2  b存储两位无符号整形数据,1010输出最低位(10)输出 2
    	return 0; 
    }

    2、性质

    位段(或称“位域”,Bit field)为一种数据结构,可以把数据以位的形式紧凑的储存,并允许对此结构的位进行操作。这种数据结构的好处:

    • 可以使数据单元节省储存空间,当程序需要成千上万个数据单元时,这种方法就显得尤为重要。

    • 位段可以很方便的访问一个整数值的部分内容从而可以简化程序源代码。

    而位域这种数据结构的缺点在于,其内存分配与内存对齐的实现方式依赖于具体的机器和系统,在不同的平台可能有不同的结果,这导致了位段在本质上是不可移植的。

    3、大小

    例1:
    #include<stdio.h>
    typedef struct Demo 
    {  
    	unsigned int a : 1;  
    	unsigned int b : 2; 
    	unsigned int c : 3; 
    }demo; 
     
    int main() 
    {  
    	demo d; 
    	printf("%d\n",sizeof(d)); //就是一个int型数据的大小 ====> 本例相当于 拿一个 int 出来一起分  
    	return 0; 
    } 
    
    
    例2:
    #include<stdio.h>
    typedef struct Demo 
    {  
    	unsigned int a : 10;   //a开辟了一个int类型空间,还剩22位
    	unsigned int b : 30;   //b是30位,不会使用A剩余的22位,会重新开辟一个int类型空间,还剩两位
    	unsigned int c : 20;   //c是20位,不会使用B剩余的两位,会重新开辟一个int类型空间
    }demo; 
     
    int main() 
    {  
    	demo d;  
    	printf("%d\n",sizeof(d));   //  12  == 3 * 4 
    	return 0; 
    } 
    例3:将上例中b与c的位置互换
    #include<stdio.h>
    typedef struct Demo 
    {  
    	unsigned int a : 10;   //a开辟了一个int类型空间,还剩22位
    	unsigned int c : 20;   //c是20位,可以继续使用A剩余的空间,此时还剩两位
    	unsigned int b : 30;   //b是30位,不会使用A剩余的两位,会重新开辟一个int类型空间
    }demo; 
     
    int main() 
    {  
    	demo d;  
    	printf("%d\n",sizeof(d));   //  8  == 2 * 4 
    	return 0; 
    } 
    例4:
    #include<stdio.h>
    struct S 
    {  
    	char ch;//1+3  
    	char *ptr;//4  
    	char buff[6];//6+2  ==> 16    
    	union ru
    	{   
    		short a;   
    		short b; 
    		short c;   
    		short d;   
    		struct st   
    		{    
    			unsigned int x : 2;    
    			unsigned int z : 10;    
    			unsigned int y : 1;   
    		}; //ss大小是 4 , 如果没有 ss 变量? 此时结构体st不占用内存空间,联合体union大小变为2 
    	}rr;  //4  如果没有 ss 变量? rr大小为2 (rr刚好使用buff浪费的两个字节) 结构体S大小将变为20  
    	struct S * p;
    }; 
    int main() 
    { 
    	printf("%d\n", sizeof(struct S));    // 大小为24 
    	return 0; 
    } 
     

     

     

    展开全文
  • 结构是用户定义的类型,而结构的声明定义了这种类型的数据属性。  一.关键字struct声明: 定义了一种新类型  struct inflatable{  char name[20];//结构成员  float volume;//结构成员  double price;//...

    •结构是用户定义的类型,而结构的声明定义了这种类型的数据属性。

      一.关键字struct声明:   定义了一种新类型

        struct inflatable{

          char name[20];//结构成员

          float volume;//结构成员

          double price;//结构成员

        } 

      定义结构之后,便可以创建这种类型的变量。如  inflatable a; inflatable b;inflatable c;由于a的类型为inflatable,因此可以使用成员运算符(.),即a.volume (访问类成员,直接用.)

             结构数组:

        inflatable结构包含一个数组,

           E  G:inflatable gifts[100];//若创建包含100个inflatable结构的数组.

              cin>>gift[0].volume;

        初始化:

           inflatable guests[2]={

              {"LELE",0.5,21.99},

              {"HAHA",2000,565.99}

           };

        二.共用体

        共用体是一种数据格式,它能够存储不同的数据类型,但只能同时存储其中的一种类型。结构可以同时存储int long double,共用体只能存储int,long,double。共用体的句法和结构相似,但含义不同。 one4all是创建的类型

        声明:  union one4all{ 

              int int_val;

              long long_val;

              double double_val;

             }

        可以使用one4all变量来存储int ,long 或double,条件是在不同的时间进行:

        one4all pail;

        pail.int_val=15;

        cout<<pail.int_val;

        pail.double_val=1.38

        cout<<pail.double_val;

        pail有时可以是int变量,有时可以是double变量。成员名称标识了变量的容量。由于共用体每次只能存储一个值,因此它必须有足够的空间来存储最大的成员,所以,共用体的长度为其最大成员的长度。

        共用体用途之一:当数据项不用同时使用两种或者更多的时候,可节省空间。假设管理一个小商品目录,其中有一些商品的ID为整数,而另一些的ID为字符串。

    struct widget{
            char brand[20];
            int type;
            union id{
                long id_num;
                char id_char[20];
            }name;
        };
        widget prize;
        if(prize.type==1){
            cin>>prize.name.id_num;
        }else
            cin>>prize.name.id_char;

     

        匿名共用体:没有名称,其成员将成为位于相同地址处的变量。

      struct widget{
            char brand[20];
            int type;
            union {
                long id_num;
                char id_char[20];
            };
        };
        widget prize;
        if(prize.type==1){
            cin>>prize.id_num
        }else
            cin>>prize.id_char;

     

        三.枚举 创建符号常量,可代替const,允许定义新类型。

        enum eg{red,orange,yellow,green,blue,violet,indigo};

        •让eg成为新类型的名称:eg被成为枚举,就如struct变量被称为就够一样。

        •将red,orange,yellow等作为符号常量,对应值为0~6,这些常量被成为枚举量。

        也可以用枚举名来声明这种类型的变量

        eg band;

        band=blue;

        band=2000;//错误的,2000不是枚举数,2000不是枚举变量的值。

        

     

    转载于:https://www.cnblogs.com/tianjiale/p/9951646.html

    展开全文
  • 结构体和共用体

    2021-04-13 20:31:55
    结构体和共用体 注:本文为学习《C语言从入门到精通》时,对部分章节总结 1、结构体 1.1、结构体类型概念 结构体是一种构造类型,由若干成员组成。成员可以是一个基本数据累心,也可以是一个构造类型。 ...
  • 共用体详解

    千次阅读 2012-10-06 21:55:44
    共用体同结构体的定义形式上相同,只是把关键字struct改为union。 有时需要把几种不同类型变量放在同有一内存区域中,见图12-6,把一个整型变量,一个字符变量,一个实型变量放在同一内存区域中,尽管三个变量...
  • ● 结构体(Structure)[在C标准中有时也称为聚合(Aggregate)]是统一在同一个名字之下一组相关变量集合,它可以包含不同类型变量 ● 结构体通常用来定义储存在文件中记录 ● 将指针和结构体联合使用,...
  • 结构体和共用体的使用及注意事项

    万次阅读 多人点赞 2016-07-25 11:07:15
    一、结构体 ...结构体:是指定义相应数据结构及相应变量。 结构体如下所示, 其中,struct是结构体关键字,一定不能省略。node是结构体名,可以省略,成为无名结构体。结构体成员可以使基本类型或者
  • 2.结构体类型定义变量时struct关键字不能省略; 3定义结构体,系统对之不分配存储单元; 4.c99标准允许对某一成员初始化; 5.不能企图输出结构体变量名来达到输出结构体目的; 6.同类结构体间可以相互赋值...
  • (3):直接定义结构体变量,只有关键字struct,没有结构名,由于没有结构名,在此定义语句后面无法再定义这个类型其他结构变量,除非把定义过程再写一遍。(不建议使用) 4.结构体有三种初始化方式: struct peolpe...
  • 文章目录结构体的定义以及赋值结构体大小和内存结构结构体数组结构体和指针结构体作为函数参数结构体嵌套结构体共用体(联合体)枚举typedef 关键字 结构体的定义以及赋值 1、复合类型在内存中存放模型: 2、...
  • (C语言)union关键字

    2021-01-18 11:26:55
    为了定义共用体,您必须使用 union 语句,方式与定义结构类似。union 语句定义了一个新数据类型,带有多个成员。union 语句格式如下: union [union tag] { member definition; member definition; ... ...
  • 结构体类型定义的一般形式如下: struct 结构体名 { 数据类型 成员1; 数据类型 成员2; 数据类型 成员3; ... }; 其中,struct是关键字,是结构体类型的标志。 关于结构体定义的注意点: 结构体的成员名可以与...
  • 一,结构体 1,结构体类型声明 2,结构体自引用 ...结构体的定义如下所示,struct为结构体关键字,tag为结构体标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结
  • union: 共用体 一、 联合说明和联合变量定义   联合也是一种新数据类型, 它是一种特殊形式变量。   联合说明和联合变量定义结构十分相似。其形式为:   union 联合名{   数据类型 成员名;   数据...
  • 数据结构 与游戏背包设计

    千次阅读 2016-08-15 20:11:29
    数据结构分为:结构体、共用体、枚举型。 结构体:在定义的时候必须要写关键字struct 然后是...共用体:在定义的时候要写关键字union,基本用法和结构体相同,唯一不同的是共用体在内存当中只能使用一块数据, 赋值
  • 共用体的声明和共用体变量定义结构十分相似。形式为: union 共用体名 { 数据类型 成员名; 数据类型 成员名; ... } 变量名; 共用体表示几个变量共用一个内存位置,在不同时间保存不同...
  • 第8章 结构体、共用体及枚举类型 8.1 结构体类型 8.1.1 结构体变量的定义与初始化 1. 结构体类型概念与定义 1) 概念:描述对象不同侧面数据结构称为结构体类型。 2) 定义: struct date { int year; ...
  • 8.2 函数定义的一般形式 99 8.3 函数的参数和函数的值 100 8.3.1 形式参数和实际参数 101 8.3.2 函数的返回值 102 8.4 函数的调用 106 8.4.1 函数调用的一般形式 106 8.4.2 函数调用的方式 106 8.4.3 被调用函数的...
  • 8.2 函数定义的一般形式 99 8.3 函数的参数和函数的值 100 8.3.1 形式参数和实际参数 101 8.3.2 函数的返回值 102 8.4 函数的调用 106 8.4.1 函数调用的一般形式 106 8.4.2 函数调用的方式 106 8.4.3 被调用函数的...
  •  共用体的声明和共用体变量定义结构十分相似。形式为:   [html] view plaincopy union 共用体名  {   数据类型 成员名;   数据类型 成员名;   ...  } 变量名; 
  • c数据类型

    2019-01-28 18:14:11
    紫色代表一级目录 粉红代表二级目录 蓝色代表三级目录 红色代表关键字 橙色代表说明 c数据类型 序号类型与描述 ...4派生类型:它们包括:指针类型、数组类型、结构类型、共用体类型和函数类型。 ...

空空如也

空空如也

1 2 3
收藏数 58
精华内容 23
关键字:

共用体结构定义的关键字