首页 > 其他 > 详细

结构体和共用体

时间:2021-02-15 23:41:01      阅读:31      评论:0      收藏:0      [点我收藏+]

结构体和共用体

1.结构体

1.1 看一个养猫问题

张老太养了两只猫猫:一只叫小白,今年3岁,白色,还有一只叫小花,今年100岁,花色,请编写一个程序,当用户输入小猫的名字,就显示该猫的名字,年龄,颜色。如果用户输入的小猫名错误,则显示张老太没有这只猫猫

1.2 使用传统技术解决

  • 单独的定义变量解决
  • 学习完数组,它是一组具有相同类型的数据的集合,在编程中,我们往往还需要一组类型不同的数据,例如猫的名字使用字符串,年龄是int,因为数据类型不同,不能用一个数组来存放

1.3 现有技术解决的缺点分析

- 不利于数据的管理和维护,因为本身猫的三个属性(名字,年龄,颜色)是一个整体,传统解决方法是将其分解-->结构体



```c
void main(){
    char cat1Name[10]="小白";
    int cat1Age=3;
    char cat1Color[10]="白色";
    
    char *catsName[2]={
        "小白"
        "小花"
    };
    int catsAge[2]{3,100}
}

1.4 结构体与结构体变量的关系示意图

把所有猫的特征提取出来---->cat结构体-数据类型(成员 name age color)

说明:除了可以有cat结构体,还可以有person结构体,有fish结构体等

1.5 快速入门--面向对象的方式解决养猫问题

#include<stdio.h>
void main(){
    //分析:
    //1.猫猫有三个成员变量组成
    //2.使用结构体解决
    
    //创建结构体cat
    struct Cat{//结构体名Cat,Cat就是我们自己构造的一个数据类型
        char *name;//名字,使用指针,指向一个字符串
        int age;
        char *color;
    };
    //使用Cat结构体创建变量
    struct Cat cat1;//cat1就是struct Cat的一个变量
    struct Cat  cat2;//cat2就是struct Cat的一个变量
    //给cat1的各个成员赋值
    cat1.name="小白";
    cat1.age=3;
    cat1.color="白色";
    
    //给cat2的各个成员赋值
    cat2.name="小花";
    cat2.age=100;
    cat2.color="花色";
    
    //输出两只猫的信息
    printf("第一只猫name=%s age=%d color=%s",cat1.name,cat1.age,cat1.color);
    printf("第二只猫name=%s age=%d color=%s",cat2.name,cat2.age,cat2.color);
    
    getchar();
}

1.6 结构体和结构体变量的区别和联系

  • 结构体是自定义数据类型,表示的是一种数据类型
  • 结构体变量代表一个具体变量
int num1;//int 是数据类型,而num1是一个具体的int变量
struct Cat cat1;//Cat是结构体数据类型,而cat1是一个Cat变量
  • Cat就像一个”模板“,定义出来的结构体变量都含有相同的成员,也可以将结构体比作图纸,将结构体变量比作零件,根据同一张图纸生产出来的零件的特征都是一样的

1.8 如何声明结构体

struct 结构体名称{//结构体名称首字母大写,比如Cat,Person

? 成员列表;

};

struct Student{
    char *name;
    int num;
    int age;
    char group;
    float score;
    //成员也可以是结构体
};

1.9 成员

  • 基本介绍

    • 从叫法上看,有些书上称为成员,有些书说结构体包含的变量
    • 成员是结构体的一个组成部分,一般是基本数据类型,也可以是数组,指针,结构体等;比如定义的Cat结构体的int age就是一个成员;
  • 注意事项即细节说明

    • 成员声明语法同变量,实例,数据类型,成员名
    • 字段的类型可以为:基本类型,数组或指针,结构体等
  • 在创建结构体变量后,需要给成员赋值,如果没有赋值就使用可能导致程序异常终止

#include <stdio.h>
 void main(){
     struct Cat(){//结构体名字建议打字大写
         char *name;
         int age;
         char *color;   
     };
     struct Cat cat1;//定义了一个结构体变量cat1
     printf("名字=%s 年龄=%d 颜色=%s",cat1.name,cat1.age,cat1.color);
     getchar();
 }
  • 不同结构体变量的成员是独立,互不影响,一个结构体变量的成员更改,不影响另一个

1.10 创建结构体和结构体变量

  • 方式一:先定义结构体,然后再创建结构体变量
struct Stu{
    char *name;
    int num;
    int age;
    char group;
    float score;
};
struct Stu stu1,stu2;
//定义了两个变量stu1和stu2,他们都是Stu类型,都由5个成员组成
//注意关键字struct不能少
  • 方式二:在定义结构体的同时定义结构体变量
struct Stu{
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1,stu2;
//在定义结构体Stu的同时,创建了两个结构体变量stu1和stu2
  • 方式三:如果只需要stu1,stu2两个变量,后面不需要再使用结构体数据类型,定义其他变量,在定义时也可以不给出结构体名
struct {
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1,stu2;
stu1.name="tom";
stu1.num=100;
//该结构体数据类型,没有名,匿名结构体
//stu1和stu2就是该结构体的两个变量

1.11 成员的获取和赋值

结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义,数组使用下标[]获取单个元素,结构体使用点号。获取结构体成员的一般格式为

结构体变量名.成员名;

struct {
    char *name;
    int num;
    int age;
    char group;
    float score;
}stu1;
stu1.name="jack";
printf("%s",stu.name);
#include<stdio.h>
void main(){
    struct Student{
        char *name;
        int num;
        int age;
        char group;
        float score;
    }stu1={"贾宝玉",11,18,‘B‘,90.50},stu2={"林黛玉",12,16,‘A‘,100};
    struct Student stu3={
        "林黛玉2",12,16,‘A‘,100
    };//在定义结构体变量时,整体赋值,需要对应
    
    struct Student stu4;
    //stu4={"林黛玉2",12,16,‘A‘,100};//这样赋值不可以
    //stu4.name="smith";
    printf("stu1.name=%s",stu1.name);
    printf("stu3.name=%s",stu3.name);
    getcahr();
}

2.结构体应用实例

2.1 步骤

  • 声明结构体,确定结构体名
  • 编写结构体的成员
  • 编写处理结构体的函数

2.2 案例

//编写一个Dog结构体,包含name(char[10]),age(int),weight(double)属性
//编写一个say函数,返回字符串,信息中包含所有成员值

//在main方法中,创建Dog结构体变量,调用say函数,将调用结果打印输出

#include<stdio.h>
struct Dog{
    char *name;
    int age;
    double weight;
};
//say 函数,返回字符串,信息中包含所有成员值
char *say(struct Dog dog){
    //将这个信息放入到一个字符串(字符数组)
    static char info[50];
    sprintf(info,"name=%s age=%d weight=%.2f",dog.name,dog.age,dog.weight);
    dog.name="小花";
    return info;
}
void main(){
    //测试
    //定义结构体变量
    struct Dog dog;
    char *info=NULL;
    dog.name="小黄";
    dog.age=1;
    dog.weight=3.4;
    info=say(dog);//结构体变量默认是值传递
    printf("小狗信息=%s",info);
    printf("main 小狗信息=%s",dog.name);
    getchar();
}

2.4 景区门票案例

  • 一个景区根据游人的年龄收取不同价格的门票
  • 请根据游人结构体(Visitor),根据年龄段决定能够购买的门票价格并输出
  • 规则:年龄>18,门票为20元,其他情况免费
  • 可以循环从控制台输入名字和年龄,打印门票收费情况,如果名字输入n,则退出程序
#include<stdio.h>
#include<string.h>

//定义结构体
struct Visitor{
    char name[10];
    int age;
    double pay;//应付票价
};
//编写函数处理业务
//说明:因为结构体默认是值传递,会拷贝一份完整数据,效率较低
//因此,为了提高效率,我们直接接收地址
void ticket(struct Visitor* visitor){
    //判断
    if((*vistor).age>18){
        (*visitor).pay=20;
    }else{
        (*visitor).pay=0;
    }
}
void main(){
    //测试
    //创建结构体变量(创建一个游客)
    struct Vistor vistor;
    //循环输入名字和年龄
    while(1){
        printf("请输入名字:");
        scanf("%s",visitor.name);
        //判断如果名字输入n,则退出程序
        if(!strcmp("n",visitor.name)){
            break;
        }
        printf("请输入游客年龄");
        scanf("%d",&visitor.age);
        //调用函数ticket,获取应付的票价
        ticket(&visitor);
        printf("游客应付票价为%.2f",visitor.pay);
    }
    printf("退出程序");
    getchar();
    getchar();
}

3.共用体

技术分享图片
|

3.2 传统方式解决

定义结构体,根据人员的职业,使用对应的成员变量

struct Person{
    char name[20];
    int num;
    char sex;
    char profession;
    float score;//学生使用score
    char cousre[20];//老师使用course
};

传统方式的问题分析:会造成空间的浪费,比如学生只使用score,但是也占用了course成员的20个字节。

  • 解决方案
    • 做struct Stu和struct Teacher[但如果职业过多,就会对应多个结构体类型,不利于管理]
    • 使用共用体

3.3 基本介绍

  • 共用体(Union)属于构造类型,它可以包含多个类型不同的成员,和结构体非常类似,但是也有不同的地方,共用体有时也被称为联合或者联合体,定义格式为

    union 共用体名{

    ? 成员列表;

    };

  • 结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员

3.4 快速入门

  • 定义共用体类型和共用体变量的三种方式(和结构体一样)
union data{
    int n;
    char ch;
    double f;
};
union data a,b,c;
union data{
    int n;
    char ch;
    double f;
}a,b,c;
union{
    int n;
    char ch;
    double f;
}a,b,c;

union data{
    int n;
    char ch;
    short m;
};
void main(){
    union data a;
    pritf("%d,%d",sizeof(a),sizeof(union data));
    a.n=0x40;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.ch=‘9‘;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.n=0x3E25AD54;
    printf("%d,%c,%d",a.n,a.ch.a.m);
}
  • 案例演示
#include<stdio.h>
union data{
    //data就是一个共用体(内存布局),包含三个成员,共享数据空间,该空间的大小以占用最大的成员为准
    int n;
    char ch;
    short m;
};
void main(){
    union data a;
    //定义一个共用体变量a
    printf("%d,%d",sizeof(a),sizeof(union data));
    a.n=0x40;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.ch=‘9‘;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.m=0x2059;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    a.n=0x3E25AD54;
    printf("%d,%c,%d",a.n,a.ch,a.m);
    getchar();
}

3.5 内存布局

3.6 内存布局分析

要深入理解为什么前面的案例输出的结果,就需要剖析共用体在内存中是如和布局的

  • 成员n,ch,m,在内存中"对齐"到一头,对ch赋值修改的是前一个字节,对m赋值修改的是前两个字节,对n赋值修改的是全部字节。也就是说,ch,m会影响到n的一部分数据,而n会影响到ch,m的全部数据
  • 上图是在绝大多数PC机上的内存分布情况,如果是51单片机,情况就会有所不同

3.7 最佳实践

#include<stdio.h>
#define TOTAL 2//人员总数

//定义了一个结构体Person
union MYUNION{
    float score;
    char score;
    char course[30];
};
struct Person{
    char name[20];
    int num;
    char sex;
    char profession;
    union{
        float score;
        char course[20];
    }sc;//sc是一个共用体变量
};
void main(){
    int i;
    struct Person person[TOTAL];//定义了一个结构体数组
    //输入人员信息
    for(i=0;i<TOTAL;i++){
        printf("input info:");
        scanf("%s %d %c %c",person[i].name,&(person[i].name),&(person[i].num),&(person[i].sex),&(person[i].profession));
        if(person[i].profession==‘s‘){
            printf("请输入该学生成绩:");
            scanf("%f",&person[i].sc.score);
        }else{
            printf("请输入该老师课程:");
            scanf("%s",person[i].sc.course);
        }
        fflush(stdin);
    }
    //输入人员信息
    printf("Name\t\tNum\tSex\tProfession\tScore\tCourse\n");
    for(i=0;i<TOTAL;i++){
        if(person[i].profession==‘s‘){
            printf("%s\t\t%d\t%c\t%c\t%c\t\t%f",persons[i].name,persons[i].num,persons[i].sex,persons[i],profession,persons[i].sc.score);
        }else{
            printf("%s\t\t%d\t%c\t\t%s",persons[i].name,persons[i].num,persons[i].sex,persons[i].profession,persons[i].sc.course);
        }
    }
    getchar();
    getchar();
}

结构体和共用体

原文:https://www.cnblogs.com/mx-info/p/14404234.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!