C语言学习笔记——结构体和共用体

简介: C语言学习笔记——结构体和共用体

1.结构体

1.1结构体代码示例

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

#include<stdio.h>
#include<string.h>
void main() {
  char name[10] = { 0 };
  struct CAT {//定义一个名字叫CAT的结构体,CAT是一种数据类型
    char* name;
    int age;
    char* color;
  };
  struct CAT cat1;//可以参照int num;来理解,都是数据类型 变量名字
  cat1.name = "小白";
  cat1.age = 3;
  cat1.color = "白色";
  struct CAT cat2;
  cat2.name = "小花";
  cat2.age = 100;
  cat2.color = "花色";
  printf("请输入猫的名字:");
  gets_s(name, sizeof(name));
  if (strcmp(name, cat1.name) == 0) {
    printf("第一只小猫的名字为%s,年龄为%d,颜色为%s\n", cat1.name, cat1.age, cat1.color);
  }
  else if (strcmp(name, cat2.name) == 0) {
    printf("第二只小猫的名字为%s,年龄为%d,颜色为%s", cat2.name, cat2.age, cat2.color);
  }
  else {
  printf("张老太没有这只猫");
}
}

d103d3dc96c142dfa3b19afea0e6b7d5.png

1.2.结构体和结构体变量的区别和联系

  1. 结构体是自定义的数据类型,表示的是一种数据类型
  2. 结构体变量代表一个具体变量,好比
int num1 ; // int 是数据类型, 而 num1 是一个具体的 int 变量
struct Cat cat1; // Cat 是结构体数据类型, 而 cat1 是一个 Cat 变量

3.Cat 就像一个“模板”,定义出来的结构体变量都含有相同的成员。也可以将结构体比作“图纸”,将结构体变量比作“零件”,根据同一张图纸生产出来的零件的特性都是一样的

1.3.结构体变量在内存的布局

16b32dc196c04ec7957f565a48fcc99a.png

定义一个Cat类型的变量cat1,数据结构类型Cat中定义了char* name,int age,char* color;在变量cat1中,char* name指向了字符串"小白",int age = 2,char* color指向了字符串"白色"

1.4.如何声明结构体

struct 结构体名称 { // 结构体名首字母大写,比如 Cat, Person 
    成员列表;
};
struct Student{ 
    char *name; //姓名 
    int num; //学号 
    int age; //年龄 
    char group; //所在学习小组 
    float score; //成绩
};

1.5.成员

1.5.1.基本介绍

成员是结构体的一个组成部分,一般是基本数据类型、也可以是数组、指针、结构体等

1.5.2.注意事项和细节说明

  1. 成员声明语法同变量,示例: 数据类型 成员名;
  2. 字段的类型可以为:基本类型、数组或指针、结构体等
  3. 在创建一个结构体变量后,需要给成员赋值,如果没有赋值就使用可能导致程序异常终止
#include <stdio.h>
void main() {
  struct Cat { // 结构体名字建议首写字母大写 
    char* name;//名字 , 这里需要使用指针类型 
    int age; //年龄 
    char* color; // 颜色 
  };
  struct Cat cat1; //定义了一个结构体变量 cat1
  printf("\n 名字=%s 年龄=%d 颜色=%s ", cat1.name, cat1.age, cat1.color);
}

b9ced81d65e140d4b191d3cbb936c066.png

4.不同结构体变量的成员是独立,互不影响,一个结构体变量的成员更改,不影响另外一个(不同的结构体占用的是不同的内存空间)

ce0f5951e685461ba473b1c7a5d30739.png

1.6.创建结构体和结构体变量

(可以参考枚举类型)

  1. 先定义结构体,然后再创建结构体变量
struct Stu{ 
    char *name; //姓名
    int num; //学号 
    int age; //年龄 
    char group; //所在学习小组 
    float score; //成绩 
};
struct Stu stu1, stu2; 
//定义了两个变量 stu1 和 stu2,它们都是 Stu 类型,都由 5 个成员组成 
//注意关键字 struct 不能少

2.在定义结构体的同时定义结构体变量

struct Stu{ 
    char *name; //姓名
    int num; //学号 
    int age; //年龄 
    char group; //所在学习小组 
    float score; //成绩 
}stu1, stu2;
//在定义结构体 Stu 的同时,创建了两个结构体变量 stu1 和 stu2

3.如果只需要 stu1、stu2 两个变量,后面不需要再使用结构体数据类型,定义其他变量,在定义时也可 以不给出结构体名

struct{ //没有写 Stu
    char *name; //姓名
    int num; //学号 
    int age; //年龄 
    char group; //所在学习小组 
    float score; //成绩 
}stu1, stu2;
stu1.name = "tom"; stu1.num = 100;....//定义方式改变
//1. 该结构体数据类型,没有名, 匿名结构体
//2. stu1 和 stu2 就是 该结构体的两个变量

1.7.成员的获取和赋值

结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[ ]获取单个元素,结构体使用点号.获取单个成员(可以理解成访问某一结构体变量的某一成员)获取结构体成员的一般格式为

结构体变量名.成员名;

1.赋值方式1:结构体变量名.成员名;

struct{ 
    char *name; //姓名 
    int num; //学号 
    int age; //年龄 
    char group; //所在小组 
    float score; //成绩 
} stu1; 
stu1.name = "jack"; //为结构体变量str1中的char* name;赋值,使其指向字符串"jack"
printf("%s", stu1.name);//printf时候输出stru1结构体中char* name所指向的字符串"jack"

2.赋值方式2:在定义完结构体后,就按顺序直接进行赋值

//在定义完结构体后,就按顺序直接进行赋值
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 = {"贾宝玉", 11, 18, 'B', 90.50};//也可以结构体定义时,按顺序赋值
struct Student stu4;
stu1 = {"贾宝玉", 11, 18, 'B', 90.50};//但不能在结构体定义完后,分开进行赋值

2.共用体

2.1.共用体基本介绍

  1. 共用体(Union)属于 构造类型,它可以包含多个类型不同的成员。和结构体非常类似,但是也有不同的地方。结构体和共用体的区别在于:结构体的各个成员会占用不同的内存互相之间没有影响;而共用体的所有成员占用同一段内存修改一个成员会影响其余所有成员
  2. 共用体有时也被称为联合或者联合体, 定义格式为
union 共用体名{
    成员列表
};

2.2.共用体代码示例

  1. 共用体的定义同结构体的三种方式一样
#include <stdio.h>
union data { // data 就是一个共用体(内存布局), 包含三个成员, 共享数据空间, 该空间的大小以占用最大的成员为准
  int n;
  char ch;
  short m;
};
void main() {
  union data a; //定义两个一个 共用体变量 a
  printf("%d, %d\n", sizeof(a), sizeof(union data)); // 4, 4
  a.n = 0x40;//16 进制
  printf("%d, %c, %d\n", a.n, a.ch, a.m);
  a.ch = '9'; // 
  printf("%d, %c, %d\n", a.n, a.ch, a.m);
  a.m = 0x2059;
  printf("%d, %c, %d\n", a.n, a.ch, a.m);
  a.n = 0x3E25AD54;
  printf("%d, %c, %d\n", a.n, a.ch, a.m);
}

20c6e50e4a4e24304abf64fb4f758ac93.png

3.过程分析

92add9e092194a5d90f2aebc35e88000.png

1.在进行到a.n = 0x40;时,由于0x40所表示的十六进制数对应的十进制数是64,并且,由于是对int类型进行赋值,因此,对a的四个字节进行赋值,将a的值设置为64,对应的内存中的二进制数为0100 0000;int需要4个字节,因此,将a的四个字节,即0000 0000 0000 0000 0000 0000 0100 0000转换为十进制数,并且输出这个十进制数,即输出64;char需1个字节,因此,将a的第一个字节,即0100 0000,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'@';short需要两个字节,因此,将a的第一个和第二个字节,即0000 0000 0100 0000转换为十进制数,并且输出这个十进制数,即输出64

c88b5ea77fdf434ea8a9f6dd8534d405.png

2.在执行到a.ch = '9';时,由于ASCII码'9'所对应的十进制数为57,内存中转换为对应的二进制数为0011 1011,并且,由于是对char类型进行赋值,因此,对a的第一个字节进行赋值,;int需要4个字节,因此,,将a的四个字节,即0000 0000 0000 0000 0000 0000 0011 1001,转换为十进制数,并且输出这个十进制数,即输出57;char需1个字节,因此,将a的第一个字节,即0011 1001,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'9';short需要两个字节,因此,将a的第一个和第二个字节,即0000 0000 0011 1001,转换为十进制数,并且输出这个十进制数,即输出57

3.c6c99e12c2b846e08ba0cf173f5a2491.png

在执行到a.m = 0x2059;时,由于十六进制数0x2059对应的十进制数为8281,内存中转换为对应的二进制数为0010 0000 0101 1001,并且,由于是对short类型进行赋值,因此,对a的第一个和第二个字节进行赋值;int需要4个字节,因此,将a的四个字节,0000 0000 0000 0000 0010 0000 0101 1001,转换为十进制数,并且输出这个十进制数,即输出8281;char需1个字节,因此,将a的第一个字节,即0101 1001,转换为十进制数,并且输出这个十进制数所对应的ASCII码,即'Y';short需要两个字节,因此,将a的第一个和第二个字节,即0010 0000 0101 1001,转换为十进制数,并且输出这个十进制数,即输出8281

0f8d155c15004040be91a2eacdbd0558.png

2.3.共用体练习

现有一张关于学生信息和教师信息的表格。学生信息包括姓名、编号、性别、职业、分数,教师的信息包括姓名、编号、性别、职业、教学科目。请看下面的表格,并请使用共用体编程完成

aa47552daaf6bd8f8850242067c9750.png

#include<stdio.h>
void main() {
  struct Information {//定义一个名字为Information的结构体
    char name[20];//字符数组name用于存放姓名
    int num;//整型num用于存放编号
    char sex;//字符sex用于存放性别
    char profession;//字符profession用于存放职业
    union SC{//在Information结构体中定义一个SC共用体,用于存放个体间不同的数据
      double score;//double类型score用于存放学生的成绩
      char course[20];//字符数组course用于存放老师的课程
    };
  };
  int i;
  struct Information studentAndTeacher[5];
  for (i = 0; i < 4; i++) {//遍历studentAndTeacher结构体数组,并存入数据
    printf("请输入名字:\n");
    scanf_s("%s", studentAndTeacher[i].name, sizeof(studentAndTeacher[i].name));
    printf("请输入编号:\n");
    scanf_s("%d", &studentAndTeacher[i].num);
    getchar();//用于接收键盘的回车
    printf("请输入性别(m/f):\n");
    scanf_s("%c", &studentAndTeacher[i].sex, sizeof(studentAndTeacher[i].sex));
    getchar();//用于接收键盘的回车
    printf("请输入职业(t/s):\n");
    scanf_s("%c", &studentAndTeacher[i].profession, sizeof(studentAndTeacher[i].profession));
    //判断之前输入的profession是t还是s
    if (studentAndTeacher[i].profession == 't') {//如果是t,则接下来输入course
      printf("请输入课程:\n");
      scanf_s("%s", studentAndTeacher[i].course, sizeof(studentAndTeacher[i].course));
    }
    else if (studentAndTeacher[i].profession == 's') {//如果是s,则接下来输入score
      printf("请输入成绩:\n");
      scanf_s("%lf", &studentAndTeacher[i].score);
    }
    else {
      printf("你输入的信息有误");
    }
  }
  printf("姓名\t编号\t性别\t职业\t课程/成绩\n");//输出表格的标题
  for (i = 0; i < 4; i++) {//遍历studentAndTeacher结构体数组,并输出数据
    printf("%s\t", studentAndTeacher[i].name);
    printf("%d\t", studentAndTeacher[i].num);
    printf("%c\t", studentAndTeacher[i].sex);
    printf("%c\t", studentAndTeacher[i].profession);
    if (studentAndTeacher[i].profession == 't') {
      printf_s("%s\n", studentAndTeacher[i].course);
    }
    else {
      printf_s("%.2f\n", studentAndTeacher[i].score);
    }
  }
}

dd9fd14a5cfe49e797f5e1abeb6c8eca.png



相关文章
|
1天前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
5天前
|
编译器 C语言 C++
C语言结构体
C语言结构体
15 5
|
13天前
|
C语言
C语言学习笔记-知识点总结上
C语言学习笔记-知识点总结上
56 1
|
13天前
|
C语言
C语言结构体链式结构之有头单链表
文章提供了一个C语言实现的有头单链表的完整代码,包括创建链表、插入、删除和打印等基本操作。
17 1
|
17天前
|
C语言
初识C语言6——结构体
初识C语言6——结构体
16 3
|
19天前
|
存储 编译器 C语言
【C语言】探索结构体基础知识:简明概要
【C语言】探索结构体基础知识:简明概要
|
1天前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
6天前
|
编译器 Linux C语言
C语言 之 结构体超详细总结
C语言 之 结构体超详细总结
9 0
|
11天前
|
存储 编译器 Linux
深入C语言:探索结构体的奥秘
深入C语言:探索结构体的奥秘
|
11天前
|
存储 编译器 C语言
c语言回顾-结构体(2)(下)
c语言回顾-结构体(2)(下)
23 0