当前位置:网站首页>015 C语言基础:C结构体、共用体
015 C语言基础:C结构体、共用体
2022-06-27 04:04:00 【入狱计划进度50%】
一:C语言结构体
1.1:概述
前面的章节学习了数组,他是一组具有相同类型的数据的集合。但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放。
在C语言中,可以使用结构体来存放一组不同类型的数据。结构体的定义形式为:
struct 结构体名{
结构体所包含的变量或数组
};
结构体是一种集合,里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称之为结构体的成员。
struct stu{
char *name; // 姓名
int num; // 学号
int age; // 年龄
char group; // 所在学习小组
float score; // 成绩
};
注意大括号后面的分号;不能少,这是一条完整的语句。
像int、float、char等是由C语言本身提供的数据类型,不能再进行分拆,我们称之为基本数据类型;而结构体可以包含多个基本类型的数据,也可以包含其他的结构体,我们将它称为复杂数据类型或构造数据类型。
1.2:结构体变量
既然结构体是一种数据类型,那么就可以用它来定义变量。例如;
struct stu stu1, stu2;
定义了两个变量 stu1 和 stu2,它们都是 stu 类型,都由 5 个成员组成。注意关键字struct不能少。
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
} stu1, stu2;
1.3:成员的获取与赋值
结构体和数组类似,也是一组数据的集合,整体使用没有太大的意义。数组使用下标[]获取单个元素,结构体使用点号.获取单个成员。
格式为:结构体变量名.成员名;
实例:
#include <stdio.h>
int main(){
struct{
char *name;
int num;
int age;
char group;
float score;
}stu1;
// 给结构体成员赋值
stu1.name = "tom";
stu1.num = 12;
stu1.age = 22;
stu1.group = 'A';
stu1.score = 123.5;
// 读取结构体成员的值
printf("%s 的学号是:%d, 年龄是 %d, 在%c组, 今年的成绩是%.1f \n", stu1.name, stu1.num, stu1.age, stu1.group,stu1.score);
}
结果:
┌──(rootkali)-[~/Desktop/c_test]
└─# ./jiegoutichengyuan
tom 的学号是:12, 年龄是 22, 在A组, 今年的成绩是123.5
除了可以对成员进行逐一赋值,也可以在定义的时候整体赋值,例如;
struct{
char *name;
int num;
int age;
char group;
float score;
} stu1, stu2 = {
"tom", 12, 22, 'A', 123.5};
需要注意的是,结构体是一种自定义的数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据,需要内存空间来存储。
二:C语言结构体数组
所谓结构体数组,是指数组中的每个元素都是一个结构体。在实际应用中,结构体数组常被用来表示一个拥有相同数据结构的群体,比如一个班的学生,一个车间的职工等。
实例:
struct stu{
char *name; // 姓名
int num; // 学号
int age; // 年龄
char group; // 所在小组
float score; // 成绩
}class[5]; // 表示一个班级有5个学生
结构体数组在定义的同时也可以初始化,例如;
#include <stdio.h>
struct stu{
char *name; // 姓名
int num; // 学号
int age; // 年龄
char group; // 所在小组
float score; // 成绩
}class[5] = {
{
"Li ping", 5, 18, 'C', 145.0},
{
"Zhang ping", 4, 19, 'A', 130.5},
{
"He fang", 1, 18, 'A', 148.5},
{
"Cheng ling", 2, 17, 'F', 139.0},
{
"Wang ming", 3, 17, 'B', 144.5}
};
获取Wang ming的成绩:class[4].score;
修改Li ping的学习小组:class[0].group = 'B';
三:C语言结构体和指针
3.1:定义结构体
指针也可以指向一个结构体,定义的形式一般为:struct 结构体名 *变量名;
实例:
下面是一个定义结构体指针的实例:
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1 = {
"Tom", 12, 18, 'A', 136.5 };
//结构体指针
struct stu *pstu = &stu1;
也可以在定义结构体的同时定义结构体指针:
struct stu{
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在小组
float score; //成绩
} stu1 = {
"Tom", 12, 18, 'A', 136.5 }, *pstu = &stu1;
注意,结构体变量名和数组名不同,数组名在表达式中会被转换为数组指针,而结构体变量名不会,无论在任何表达式中它表示的都是整个集合本身,要想取得结构体变量的地址,必须在前面加&,所以给 pstu 赋值只能写作:struct stu *pstu = &stu1;而不能写作:struct stu *pstu = stu1;
还应该注意,结构体和结构体变量是两个不同的概念:结构体是一种数据类型,是一种创建变量的模板,编译器不会为它分配内存空间,就像 int、float、char 这些关键字本身不占用内存一样;结构体变量才包含实实在在的数据,才需要内存来存储。
下面的写法是错误的,不可能去取一个结构体名的地址,也不能将它赋值给其他变量:
struct stu *pstu = &stu;
struct stu *pstu = stu;
3.2:获取结构体成员
两种形式(等效,通常采用后者,更加直观):
(*pointer).memberName
.的优先级高于*,并且()也不能省略,若是省略则等价于:*(pointer.memberName)
pointer->memberName
有了->,就可以通过结构体指针直接去的结构体成员,这也是->在C语言中的唯一用途
看下例子:
实例1:
#include <stdio.h>
int main(){
struct{
char *name;
int num;
int age;
char group;
float score;
}stu1 = {
"tom", 12, 18, 'A', 136.5}, *pstu = &stu1;
// 读取结构体成员你的值
printf("%s的学号是%d, 年龄是%d, 在%c组, 今年的成绩是%.1f \n", (*pstu).name, (*pstu).num, (*pstu).age, (*pstu).group, (*pstu).score);
printf("%s的学号是%d, 年龄是%d, 在%c组, 今年的成绩是%.1f \n", pstu->name, pstu->num, pstu->age, pstu->group, pstu->score);
}
结果:
┌──(rootkali)-[~/Desktop/c_test]
└─# ./jiegoutizhizhen
tom的学号是12, 年龄是18, 在A组, 今年的成绩是136.5
tom的学号是12, 年龄是18, 在A组, 今年的成绩是136.5
实例2:
#include <stdio.h>
struct stu{
char *name; // 姓名
int num; // 学号
int age; // 年龄
char group; // 所在小组
float score; // 成绩
}stus[] = {
{
"Zhou ping", 5, 18, 'C', 145.0},
{
"Zhang ping", 4, 19, 'A', 130.5},
{
"Liu fang", 1, 18, 'A', 148.5},
{
"Cheng ling", 2, 17, 'F', 139.0},
{
"Wang ming", 3, 17, 'B', 144.5}
},*ps;
int main(){
// 求数组长度
int len = sizeof(stus) / sizeof(struct stu);
printf("Name\t\tNum\tAge\tGroup\tScore\t\n");
for(ps=stus; ps<stus+len; ps++){
printf("%s\t%d\t%d\t%c\t%.1f \n", ps->name, ps->num, ps->age, ps->group, ps->score);
}
return 0;
}
结果:
┌──(rootkali)-[~/Desktop/c_test]
└─# ./jiegoutishuzuzhizhen
Name Num Age Group Score
Zhou ping 5 18 C 145.0
Zhang ping 4 19 A 130.5
Liu fang 1 18 A 148.5
Cheng ling 2 17 F 139.0
Wang ming 3 17 B 144.5
四:C语言共用体
结构体(struct)是一种构造类型或复杂类型,可以包含多个类型不同的成员。在C语言中还有另一种和结构体非常类似的语法,叫做共用体(union)。
定义格式为:
union 共用体名{
成员列表
};
区别:
结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。
共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。
共用体也是一种自定义类型,可以通过它来创建变量,例如:
union data{
int n;
char ch;
double f;
};
union data a, b, c;
上面是先定义共用体,再创建变量,也可以在定义共用体的同时创建变量:
union data{
int n;
char ch;
double f;
} a, b, c;
共用体data中,成员f占用的内存最多,为8个字节,所以data类型的变量(也就是a,b,c)也占用8个字节的内存。
实例:
#include <stdio.h>
union data{
int n;
char ch;
short m;
};
int main(){
union data a;
printf("%d, %d\n", sizeof(a), sizeof(union data) );
a.n = 0x40;
printf("%X, %c, %hX\n", a.n, a.ch, a.m);
a.ch = '9';
printf("%X, %c, %hX\n", a.n, a.ch, a.m);
a.m = 0x2059;
printf("%X, %c, %hX\n", a.n, a.ch, a.m);
a.n = 0x3E25AD54;
printf("%X, %c, %hX\n", a.n, a.ch, a.m);
return 0;
}
结果:
┌──(rootkali)-[~/Desktop/c_test]
└─# ./gongyongti
4, 4
40, @, 40
39, 9, 39
2059, Y, 2059
3E25AD54, T, AD54
这段代码不但验证了共用体的长度,还说明共用体成员之间会相互影响,修改一个成员的值会影响其他成员。
边栏推荐
- 016 C语言基础:C语言枚举类型
- QChart笔记2: 添加鼠标悬停显示
- Kotlin Compose 自定义 CompositionLocalProvider CompositionLocal
- 2022-06-26:以下golang代码输出什么?A:true;B:false;C:编译错误。 package main import “fmt“ func main() { type
- 苹果唯一图谱架构常识
- resnet152 辣椒病虫害图像识别1.0
- fplan-Powerplan实例
- Is the truth XX coming? Why are test / development programmers unwilling to work overtime? This is a crazy state
- 1.5 conda的使用
- 2021:Passage Retrieval for Outside-KnowledgeVisual Question Answering通道检索的外部知识视觉问答
猜你喜欢

Facing the "industry, University and research" gap in AI talent training, how can shengteng AI enrich the black land of industrial talents?

WPF 开源控件库Extended WPF Toolkit介绍(经典)

How can e-commerce products be promoted and advertised on Zhihu?

math_ Number set (number set symbol) and set theory

静态时序分析-OCV和time derate

Learn crypto from Buu (Zhou Geng)

GAMES101作业7提高-微表面材质的实现过程

办公室VR黄片,骚操作!微软HoloLens之父辞职!

如何让 EF Core 6 支持 DateOnly 类型

2020:MUTANT: A Training Paradigm for Out-of-Distribution Generalizationin Visual Question Answering
随机推荐
016 C语言基础:C语言枚举类型
022 C语言基础:C内存管理与C命令行参数
2022-06-26:以下golang代码输出什么?A:true;B:false;C:编译错误。 package main import “fmt“ func main() { type
2022-06-26: what does the following golang code output? A:true; B:false; C: Compilation error. package main import “fmt“ func main() { type
017 C语言基础:位域和typedef
Installation of low code development platform nocobase
How to systematically learn LabVIEW?
卷积神经网络(CNN)网络结构及模型原理介绍
Cultural tourism night tour | stimulate tourists' enthusiasm with immersive visual experience
iOS开发:对于动态库共享缓存(dyld)的了解
ERP demand and sales management Kingdee
2019LXMERT:Learning Cross-Modality Encoder Representations from Transformers
2016Analyzing the Behavior of Visual Question Answering Models
2021:Graphhopper: Multi-Hop Scene Graph Reasoning for Visual Question Answering
Method of decoding iPhone certificate file
Fplan layout
WPF open source control library extended WPF toolkit Introduction (Classic)
通信中的机器学习最佳阅读资料列表
手机新领域用法知识
使用promise的基本功能【四、Promise源码】