zoukankan      html  css  js  c++  java
  • 结构体、公用体、枚举

    一.结构体类型

     1.结构体变量的定义与使用

      ♦ 定义结构体变量的方式

        • 先申明结构体类型再定义变量名

          struct stu  //stu:结构体类型名

          {

            成员列表

          };

          struct stu Lucy;  //Lucy:结构体变量名

        • 在声明类型的同时定义变量

          struct stu  //stu:结构体类型名

          {

            成员列表

          }Lucy,Bob;  //Lucy、Bob:结构体变量名

        • 直接定义结构体类型变量(无类型名)

          struct   //无类型名

          {

            成员列表

          }Lucy、Bob;  //Lucy、Bob:结构体变量名

      • 结构体类型名:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际的内存单元。

      • 结构体变量名:实际分配空间——为了能在结构体中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据。

      ♦ 比较推荐的写法

        typedef struct stu

        {

          成员列表

        }STU;  //使用typedef重新定义一个结构体类型名

        STU Lucy,Bob;  //使用STU去定义相应的对象

        类型与变量分开定义,当一个结构体类型有多个文件需要使用时,可以将类型定义放在放在一个.h文件中,需要使用的文件包含相应的头文件即可。

      ♦ 注意事项:

        1.结构体变量成员必须单独使用:结构体变量名.成员名

          例如:Lucy.num  = 101;

             scanf("%c",&Lucy.sex);

             printf("%s ",Lucy.name);

        2.具有相同类型的结构体变量可以相互赋值,多用于结构体成员整体操作(排序等)

          例如:Bob = Lucy;

        3.结构体可以在定义的时候进行初始化

          例如:STU Lucy = {12,"hello",'m'};

        4.允许嵌套定义结构体变量,成员引用多级引用

          例如:Lucy.birthday.month = 12;

    #include <stdio.h>
    
    typedef struct stu
    {
        int num;
        char name[10];
        char sex;
    }STU;
    
    int main(int argc,char *argv[])
    {
        STU boy1,boy2,girl = {15,"lucy",'w'};
        printf("input boy2 num name sex:");
        scanf("%d %s %c",&boy2.num,boy2.name,&boy2.sex);
        boy1 = boy2;
        printf("boy1.num = %d,boy1.name = %s,boy1.sex = %c
    ",boy1.num,boy1.name,boy1.sex);
        printf("boy2.num = %d,boy2.name = %s,boy2.sex = %c
    ",boy2.num,boy2.name,boy2.sex);
        printf("girl.num = %d,girl.name = %s,girl.sex = %c
    ",girl.num,girl.name,girl.sex);
        return 0;
    }

     2.结构体数组

      ♦ 结构体数组中每个数组元素都是一个结构体类型的数据

      ♦ 直接定义结构体数组

        struct student

        {

          int num;

          char name[10];

          int age;

        }edu[2];

      ♦ 结构体数组的引用

        edu[0].num  = 10;

        strcpy(edu[0].name,"Lucy");

        edu[0].age = 24;

    //定义一个结构体数组
    #include <stdio.h>
    
    typedef struct stu
    {
        int num;
        char name[10];
        float score;
    }STU;
    
    int main(int argc,char *argv[])
    {
        STU msg[3] = {
                        {15,"lucy",88.5},
                        {16,"peter",91.5},
                        {101,"bob",62.5}
                     };
        int i;
        float aver,sum = 0;
        
        for(i = 0;i < 3;i++)
        {
            sum = sum + msg[i].score;
        }
        aver = sum/3;
        printf("axer = %f
    ",aver);
        return 0;
    }

     3.结构体指针

       指向结构体变量首地址的指针,通过结构体指针即可访问该结构体变量

      ♦ 结构体指针变量定义:

        struct 结构体名 *结构体指针变量    例如:struct student *p  =  &Lucy;

      ♦ 利用结构体指针变量访问结构体变量的各个成员

        1.Lucy.num = 101;

        2.(*p).num = 101;

        3.p->num = 101;  //"->"称为指向运算符

        4.(&Lucy)->num  = 101;

      ♦ 结构体指针主要用于结构体变量传参以及链表中

    //利用结构体指针变量访问结构体变量的成员
    #include <stdio.h>
    
    typedef struct stu
    {
        int num;
        char name[10];
        float score;
    }STU;
    
    int main(int argc,char *argv[])
    {
        STU Lucy = {100,"Lucy",80};
        STU *p = &Lucy;
        printf("num = %d,num = %d
    ",Lucy.num,p->num);
        printf("name = %s,name = %s
    ",Lucy.name,(*p).name);
        printf("score = %.2f,score = %.2f
    ",Lucy.score,(&Lucy)->score);
        return 0;
    }

     4.结构体的内存分配

      ♦ 结构体对其,默认对其原则

       1.数据类型对其值:

          char型数据自身对其值为1,short为2,int、float为4,double(windows:8,Linux:4)

          解释:

          char变量只要有一个空余的字节即可存放

          short要求首地址能被2整除

          int、float、double同理

       2.结构体的对其值:

         其成员中自身对其值最大的那个值

         解释:

         结构体最终对其按照数据成员中最长的类型的整数倍

       3.分析以下结构体所占空间大小

    struct stu1
    {
        char a;
        int b;
        short c;
    }STU1;    //sizeof(STU1) = 12
    
    struct stu2
    {
        int b;
        char a;
        short c;
    }STU2;    //sizeof(STU2) = 8
    
    struct stu3
    {
        char a;
        int b;
    }STU3;    //sizeof(STU3) = 8

      ♦ 指定对其原则:使用#pragma pack改变默认对其原则

       1.格式:#pragma pack(value)  //value:指定对其值

         • value只能是:1 2 4 8

         • 指定类型值与数据类型对其值相比取较小值

           例如:设为1:则short、int、float等均为1

              设为2:则char仍为1,short为2,int变为2

       2.分析一下结构体所占空间大小

    #pragma pack (1)
    struct stu
    {
        char a;
        int b;
        short c;
    }STU;    //sizeof(STU) = 7
    
    #pragma pack (8)
    struct stu1
    {
        char a;
        int b;
        short c;
    }STU;    //sizeof(STU) = 12

     5.位段的使用

      ♦ 位段的定义

        struct packed_data

        {

          unsigned int a:2;

          unsigned int b:6;

          unsigned int c:4;

          unsigned int d:4;

          unsigned int i;  

        }data;  //其中a,b,c,d分别占2位,6位,4位,4位,i为整型占字节(32位)

      ♦ 位段的使用

        data.a = 2;  //赋值时,不要超出位段定义的范围;如果位段成员a定义为2位,最大值为3,即(11)2,所以data a = 5,就会取5的低两位进行赋值

      ♦ 位段定义的重要说明

        1.位段成员的类型必须指定为整型或字符型,即char、short、int、long型,不能是浮点型,也不能定义位段数组。

        2.一个位段必须存放在一个存储单元中,不能跨两个单元,即第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段

        3.位段的长度不能大于存储单元的长度。

        4.如果一个位段要从下一个存储单元开始,可以定义:

          unsigned a:1;

          unsigned b:2;

          unsigned  :0;  //长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放,将a、b存储在一个存储单元中,c另存在下一个单元

          unsignde c:3;(另一个位段)

        5.可以定义无意义的位段,如:

          unsigned int a: 1;

          unsigned int  : 2;

          unsigned int b: 3;

    #include <stdio.h>
    
    typedef struct
    {
        unsigned int a:1;
        unsigned int b:2;
        unsigned int c:3;
    }M;    //sizeof(M) = 4
    
    typedef struct b
    {
        unsigned int a:1;
        unsigned int b:2;
        unsigned int c:32;
    }B;    //sizeof(B) = 8
    
    int main(int argc,char *argv[])
    {
        M k;
        k.a = 1;
        printf("k.a = %d
    ",k.a);    //k.a = 1
        k.b = 1;
        printf("k.b = %d
    ",k.b);    //k.b = 1
        // k.b = 4;
        // printf("k.b = %d
    ",k.b);    //k.b = 0
        k.c = 4;
        printf("k.c = %d
    ",k.c);    //k.c = 4
        
        // printf("k.a_len = %d
    ",sizeof(k.a));    //错误,sizeof()是测字节长度,k.a是位段
        printf("M_len = %d
    ",sizeof(M));    //M = 4
        printf("B_len = %d
    ",sizeof(B));    //B = 12
        return 0;
    }

     二.共用体类型(联合体类型)

     ♦ 共用体的定义

       与结构体非常类似,有三种方式,推荐使用以下这种方式

       typedef union data

       {

         short int num;  //短整型2字节

         char sex;  //字符型1字节

         float score;  //浮点型4字节

       }DATA;

       DATA a,b;

     ♦ 共用体的引用

       a.num(引用共用体变量中的整型变量num)

       a.sex(引用共用体变量中的字符型变量sex)

       a.score(引用共用体变量中的实型变量score)

     ♦ 共用体的特点

       • 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只能存放其中一个成员,只有一种起作用,而不是同时存放几个。也就是说,在共用体变量中只能存放一个值。

       • 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖。

       • 共用体变量的地址和它的各成员的地址都是同一地址。

       • 共用体变量的初始化,但初始化表中只能有一个常量。

         例如:union data a={123};  //初始化共用体为第一个成员

       • 共用体变量所占的内存长度等于最长的成员的长度,而结构体变量所占的内存长度是各成员占的内存长度之和。

    //共用体
    #include <stdio.h>
    
    typedef union stu
    {
        char x;
        short int y;
        int z;
        double m;
    }STU;    //sizeof(STU) = 8
    
    int main(int argc,char *argv[])
    {
        STU a={10};
        union stu *p = &a;
        a.x = 5;
        a.y = 6;
        a.z = 15;
        printf("a.x+a.y = %d
    ",a.x+a.y);    //a.x+a.y=30,起作用的是最后一次存放的成员的值
        printf("STU_len = %d
    ",sizeof(STU));    //STU_len = 8,共用体变量所占的内存长度等于最长的成员的长度
        printf("p = %p
    ",p);    //p = 0xbfdd7c84,共用体变量的地址和它的各成员的地址都是同一地址
        printf("p->x = %p
    ",&(p->x));    //p->x = 0xbfdd7c84
        printf("p->y = %p
    ",&(p->y));    //p->y = 0xbfdd7c84
        printf("p->z = %p
    ",&(p->z));    //p->z = 0xbfdd7c84
        printf("p->m = %p
    ",&(p->m));    //p->m = 0xbfdd7c84
        return 0;
    }

    三.枚举类型

        将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。

      ♦ 枚举类型的定义

        enum 枚举名

        {

          枚举值表

        };

        • 在枚举值表中应列出所有可用值,也称为枚举元素。

        • 枚举变量仅能取枚举值所列元素。

          例如:enum week  //week为枚举类型

             {

               sun,mon,tue,wed,thu,fri,sat  //枚举元素(枚举常量)

             };

             enum week workday,weekday;  //workday、weekday为枚举变量

          • workday与weekday只能取sun……sat中的一个

            例如:workday = mon;  //正确

               weekday = tue  //正确

               workday = abc  //错误,枚举之中没有abc

      ♦ 枚举类型的注意事项

        1.枚举值是常量,不能在程序中用赋值语句再对它赋值。

          例如:sun = 5;  mon = 2;   thu = hel;  //都是错误的

        2.每一个枚举元素都代表一个整数,C语言在编译时按定义时的顺序默认它们的值为0,1,2,3,……。

          例如:在上面week的定义中,sun值为0,mon值为1,……,sat值为6

        3.可以改变枚举值的默认值。

          例如:enum week

          {

            sun=3,mon,tue,wed,thu,fri,sat

          };  //此时sun=3,mon=4,tue=5,……以此类推……,sat=9

        4.枚举元素可以用来作判断比较,枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。

          例如:if(workday == mon) ......

             if(workday > sun) ......

        5.枚举变量就是一整型变量。

        6.枚举也可以定义数组。

          例如:enum week a[10];

    //共用体
    #include <stdio.h>
    
    enum week
    {
        sun = 2,mon,tue,wed,thu,fri,sat    //mon = 3,tue = 4,……,sat = 9
    }a,b,c;
    
    enum bool
    {
        false,true    //false = 0,true = 1
    }bl;
    
    int main(int argc,char *argv[])
    {
        a = sun;
        b = mon;
        c = tue;
        printf("a = %d
    ",a);    //a = 2
        printf("b = %d
    ",b);    //b = 3
        printf("c = %d
    ",c);    //c = 4
        
        // sun = 100;    //错误,枚举值是常量,不可改
        // printf("sun = %d
    ",sun);
        a = 100;    //枚举变量可以改
        printf("a = %d
    ",a);    //a = 100
        
        printf("a_len = %d
    ",sizeof(a));    //a_len = 4,枚举变量就是一整型变量
    
        bl = true;
        if(bl == true)
            printf("bl为真
    ");
            
        bl = 1;
        if(bl == true)    //枚举元素可以用来作判断比较
            printf("bl为真
    ");
        return 0;
    }
  • 相关阅读:
    get_json_object 用法
    vim中的特殊字符
    vim常用命令
    mac下如何配置用户的环境变量
    vim如何替换^M ?
    git ssh 配置
    mac上pip install时提示/System/Library/... 无权限
    mysql语句--table中某列有多值时,删除其他,仅保留1条
    mysql语句如何把多行的数据合并到一行?
    微服务分布式电商项目学习笔记(二)---- 微服务架构图+微服务划分图(2020/7/1)
  • 原文地址:https://www.cnblogs.com/lemongirl/p/7899243.html
Copyright © 2011-2022 走看看