7.C语言结构体篇
结构体的定义
- 自定义的数据类型
- 有一批数据组合而成的结构类型数据
- 其中的每一个数据都是结构体的“成员”
- 其实就相当于Java中的类(当然没有Java中的类那么好用就是了)
格式
struct 结构体名
{
成员1(理解成Java类中的属性就好);
成员2;
。。。
}
如何使用
在函数中:struct 结构体名 自定义变量名;
#include<stdio.h>
#include<string.h>
struct Student
{
char name[100];
int age;
};
int main()
{
//第一种初始化方法
struct Student st1;
strcpy(st1.name, "张三");
st1.age = 20;
printf("学生1的名字是:%s\n学生的年龄是:%d\n", st1.name, st1.age);
//第二种初始化方法
struct Student st2 = { "李四", 21 };
struct Student st3 = { "王五", 22 };
struct Student st4 = { "赵六", 23 };
printf("\n学生2的名字是:%s\n学生的年龄是:%d\n", st2.name, st2.age);
printf("\n学生3的名字是:%s\n学生的年龄是:%d\n", st3.name, st3.age);
printf("\n学生4的名字是:%s\n学生的年龄是:%d\n", st4.name, st4.age);
return 0;
}
别名
格式:
typedef struct (可选)结构体名
{
成员. . .
} 别名;
好处:
- 使用时可以直接使用别名,不再需要带上前缀“struct”
结构体作为函数参数
- 函数中可以传递结构体
- 传递结构体的数据值
- 传递结构体的地址值
#include<stdio.h>
#include<string.h>
typedef struct Student
{
char name[100];
int age;
} S;
void reS(S* p);
int main()
{
S stu1;
strcpy(stu1.name, "aaa");
stu1.age = 0;
printf("修改前的学生姓名是:%s 年龄是:%d\n", stu1.name, stu1.age);
reS(&stu1);
printf("\n修改后的学生姓名是:%s 年龄是:%d\n", stu1.name, stu1.age);
return 0;
}
//定义一个函数,修改学生的数据
void reS(S* p)
{
printf("\n请输入要修改的名称:");
scanf("%s", (*p).name);
printf("请输入要修改的年龄:");
scanf("%d", &((*p).age));
}
结构体嵌套
- 结构体中成员的类型是其他的结构体
#include<stdio.h>
#include<string.h>
typedef struct Massage
{
char phone[12];
char meil[100];
}M;
typedef struct Student
{
char name[100];
int age;
char sex;
double height;
M massage;
}S;
int main()
{
//第一种初始化赋值方式
S s1;
strcpy(s1.name, "张三");
s1.age = 23;
s1.sex = 'F';
s1.height = 1.73;
strcpy(s1.massage.phone, "12345678901");
strcpy(s1.massage.meil, "1234567890@qq.com");
printf("姓名为:%s\n年龄为:%d\n性别为:%c\n身高为:%.2lf\n手机号为:%s\n联系邮箱为:%s", s1.name, s1.age, s1.sex, s1.height, s1.massage.phone, s1.massage.meil);
printf("\n------------------------------\n");
//第二种初始化赋值方式
S s2 = { "李四", 25, 'F', 1.83, {"12345678901", "1234567890@qq.com"} };
printf("姓名为:%s\n年龄为:%d\n性别为:%c\n身高为:%.2lf\n手机号为:%s\n联系邮箱为:%s", s2.name, s2.age, s2.sex, s2.height, s2.massage.phone, s2.massage.meil);
return 0;
}
结构体内存对齐机制
-
确定变量位置:只能放在自己类型整数倍的内存地址上
-
最后一个补位:结构体的总大小,是最大类型的整数倍
-
struct num { double a; // 8 char b; // 1 + 3 int c; // 4 char d; // 1 + 7 }
| 地址 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17+7 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 变量 | a | a | a | a | a | a | a | a | b | \0 | \0 | \0 | c | c | c | c | d | \0+7 |
-
\0:C自动填补的空字节 (我自己定义的,好记好写)
-
\0 + 7:总共7个空字节
-
习俗:
- 在定义数据类型时,按照数据类型占用字节从小到大的顺序进行定义(尽最大可能规避掉C自动填补的空洞字节)
共同体(共用体/联合体)
- 作用,可以同时接收一个含义的不同数据类型
- 格式:(也可以像结构体那样起别名“typedef”)
union 共同体名
{
数据类型1;
数据类型2;
. . .
}
- 特点:
- 所有的变量都使用同一个内存空间
- 所占内存大小 = 最大单个成员的长度(也受内存对齐影响)
- 总大小一定是最大单个成员长度的整数倍(内存对齐)
- 每次只能给一个变量进行赋值,第二次赋值时会覆盖上一次赋值的数据(原因:第一个特点)
#include<stdio.h>
#include<string.h>
//定义一个共同体
typedef union Money
{
int moneyi;
double moneyd;
char moneystr[100];
} M;
int main()
{
M m;
// 查看内存地址
printf("%p\n", &m.moneyi); // 000000C40C78F790
printf("%p\n", &m.moneyd); // 000000C40C78F790
printf("%p\n", &m.moneystr); // 000000C40C78F790
// 查看所占内存大小
printf("\n%zu\n", sizeof(m.moneyi)); // 4
printf("%zu\n", sizeof(m.moneyd)); // 8
printf("%zu\n", sizeof(m.moneystr)); // 100
printf("%zu\n\n", sizeof(m)); // 104(内存对齐)
// 查看后数据是否会覆盖前数据
m.moneyi = 100;
printf("%d\n", m.moneyi); // 100
m.moneyd = 99.5;
printf("%.2lf\n", m.moneyd); // 99.50
strcpy(m.moneystr, "100万");
printf("%s\n", m.moneystr); // 100万
return 0;
}
结构体和共同体的区别
- 结构体:
- 一种事物中包含多个属性(和Java中类的概念类似)
- 存储方式:各存各的
- 内存占用:各个变量的总和(受内存对齐影响)
- 共用体:
- 一个属性有多种类型
- 存储方式:存一起,多次存会覆盖
- 内存占用:最大类型(受内存对齐影响)

浙公网安备 33010602011771号