当前位置:网站首页>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
这段代码不但验证了共用体的长度,还说明共用体成员之间会相互影响,修改一个成员的值会影响其他成员。
边栏推荐
- 022 C语言基础:C内存管理与C命令行参数
- 使用promise的基本功能【四、Promise源码】
- Quickly master asp Net authentication framework identity - reset password by mail
- Static timing analysis OCV and time derive
- Products change the world
- Usage knowledge of mobile phones in new fields
- Baidu PaddlePaddle's "universal gravitation" first stop in 2022 landed in Suzhou, comprehensively launching the SME empowerment plan
- GAMES101作业7提高-微表面材质的实现过程
- 2021:Zero-shot Visual Question Answering using Knowledge Graphs使用知识图的零次视觉问答
- fplan-Powerplan实例
猜你喜欢
Kotlin compose implicitly passes the parameter compositionlocalprovider
低代码开发平台NocoBase的安装
卷积神经网络(CNN)网络结构及模型原理介绍
手撸promise【二、Promise源码】【代码详细注释/测试案例完整】
MySQL development environment
Building lightweight target detection based on mobilenet-yolov4
深潜Kotlin协程(十五):测试 Kotlin 协程
Anaconda3 is missing a large number of files during and after installation, and there are no scripts and other directories
2021:Greedy Gradient Ensemble for Robust Visual Question Answering
Matlab | visualization of mathematical properties related to three interesting circles
随机推荐
Kotlin Compose 自定义 CompositionLocalProvider CompositionLocal
fplan-电源规划
Fplan layout
缓存综合项目--秒杀架构
Quickly master asp Net authentication framework identity - reset password by mail
Kotlin Compose 隐式传参 CompositionLocalProvider
In a sense, the Internet has become an incubator and a parent
Six possible challenges when practicing Devops
2022-06-26: what does the following golang code output? A:true; B:false; C: Compilation error. package main import “fmt“ func main() { type
1.5 use of CONDA
Kotlin compose compositionlocalof and staticcompositionlocalof
021 C语言基础:递归,可变参数
Ledrui ldr6035 usb-c interface device supports rechargeable OTG data transmission scheme.
WPF open source control library extended WPF toolkit Introduction (Classic)
[BJDCTF2020]The mystery of ip
Il manque beaucoup de fichiers et de répertoires tels que scripts pendant et après l'installation d'anaconda3
Network structure and model principle of convolutional neural network (CNN)
Installation of low code development platform nocobase
windows上安装MySQL
深潜Kotlin协程(十五):测试 Kotlin 协程