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



目录
打赏
0
0
0
0
19
分享
相关文章
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
261 14
【C语言】结构体详解 -《探索C语言的 “小宇宙” 》
结构体通过`struct`关键字定义。定义结构体时,需要指定结构体的名称以及结构体内部的成员变量。
238 10
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
380 13
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
140 12
C 语言结构体 —— 数据封装的利器
C语言结构体是一种用户自定义的数据类型,用于将不同类型的数据组合在一起,形成一个整体。它支持数据封装,便于管理和传递复杂数据,是程序设计中的重要工具。
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
101 4
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
161 10
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
C语言结构体
C语言结构体
45 5
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等