目录
一、基础知识
1.1 概念:
描述一个复杂的数据类型,该类型 struct 需要若干个不同的数据类型的变量组成。(由程序开发者自己设计的类型)
例如:学生
姓名,学号,年龄,性别这些内容都是不同数据类型的。我们无法使用数组或其他基本数据类型来
描述,因此我们需要一个复合如下要求的变量
①变量能够存储多个数值
②数值的数据类型不同
③这些数值共同组成了一个整体用于描述同一种事物
C语言提供了一种复合数据类型来保存这种数据—结构体类型,用户可以自行定义其中的内容用来
描述一个全新的类型。
1.2 语法格式
①声明:
struct 结构体类型名
{
数据类型 变量名;(结构体成员)
……
};
struct Stu
{
char _name[100];
int id;
int age;
char sex;
};
② 声明结构体变量
struct 结构体类型名 结构体变量名;
//变量声明
struct Stu s1;
③ 初始化结构体变量
struct 结构体类型名 结构体变量名={值1,值2,。。。值n};
//初始化
struct Stu s2 = { "小强", 1, 21, 'F' };
struct Stu s3 = { "丧彪", 2 };
s3.age = 19;
s3.sex = 'M';
printf("我叫%s,我的学号是%d,我今年%d岁了,我的性别是%c\n", s3._name, s3.id, s3.age, s3.sex);
④ 结构体变量成员的使用
结构体变量名.成员名
1.3 结构体的嵌套
结构体变量可以嵌套定义
struct A
{
成员;
};
struct B
{
struct A 变量;
};
struct Date
{
int year;
int month;
int day;
};
struct Phone
{
char _name[50];
int price;
struct Date date;
};
二、结构体变量的大小
2.1 概念
个结构体变量的大小是由以下两个条件共同决定的:
①结构体内部的成员变量的大小
②字节对齐规则 :
内存大小的基本单位是字节(byte),理论上来讲,可以从任意地址访问变量,但是实际上
CPU并非逐字节读写内存,而是以2、4、或8的倍数的字节块来读写内存,因此就会对基本数据类
型的地址做出一些限制。即它的地址,必须是2、4、或8的倍数。那么就要求各种数据类型按照一
定的规则在空间上排列,这就是对齐。
2.2 计算
以结构体内部最大元素的所占内存的大小作为内存的基本分配单元,一个结构体的大小是这个结构
体中最大元素的内存单元的整数倍;结构体变量的存储是有条件的“连续存储”。因为每次分配的内
存大小都是最大成员变量内存大小的整数倍所以在其中是有“空洞”空间的。
所占内存大小:8字节
所占内存大小:8字节
所占内存大小:16字节,原因:结构体变量的存储是有条件的“连续存储”。因为每次分配的内存大
小都是最大成员变量内存大小的整数倍所以在其中是有“空洞”空间的。
本来按分配原则:double的3倍,24字节,但是因为存储是连续的,给第一个x分配8个字节,它本
身占4个,有4个空洞,又因为存储连续,下一个字节继续放c,共用所分配的8字节。
嵌套结构体类型,所占内存:
所占内存:24 byte ,Stu中最大的数据类型所占8字节,以其作为基类型*3
给数据,看下具体内存中是怎么存储的:
三、指针和结构体
3.1 指针变量指向结构体
需要创建一个基类型是结构体类型的指针变量。
结构体的地址就是结构体中第一个成员的首字节地址。
3.1.1 利用指针变量访问结构体变量中的成员
语法:指针变量名->结构体成员名
利用指针变量加*来当做变量本身,需要将*和指针变量利用括号括起来,否则,指针变量首先会和.
运算先结合。
(*指针变量名).成员
两种访问方式都可以访问到结构体中的a变量的值。
3.1.2 取结构体变量中的成员的地址
&结构体变量名.成员 &info.x &info.data.a
&结构体指针变量->成员 &p->a
#include <stdio.h>
struct DATA
{
int a;
char b;
double c;
};
struct Info
{
int x;
int y;
struct DATA data;
};
int main()
{
struct DATA data = { 12, 'A', 0.9 };
struct DATA* p = NULL;
p = &data;//p == &data
printf("%d\n", sizeof(p));
printf("%p %c %.3lf\n", &p->a, p->b, p->c);
struct Info info = { 7, 8, { 100, 'B', 3.14 } };
printf("%p\n", &info.x);
printf("%p\n", &info.data.a);
}
3.2 结构体内有指针变量作为成员
定义一个结构体,有一个x变量,一个指针p。
#include <stdio.h>
struct Num
{
int x;
int* p;
};
int main()
{
int m = 999;
struct Num obj = { 0, &m }; // 指针p保存的是m的地址
printf("%d %p\n", obj.x,obj.p); // obj.p访问到的是p指针保存的地址
printf("%d\n", *(obj.p)); //*才能访问到p指针地址上存的数值
}
3.3 结构体变量充当函数参数
概念:形式参数是结构体变量名,意味着参数在传递时,由实际参数(结构体变量)传递给形式参
数(结构体变量)。实际上适合普通变量的参数传递一样的。
返回值类型 函数名(struct 结构体类型名 变量名)
{
}
#include <stdio.h>
struct Stu
{
char _name[50];
int id;
};
void Fun(struct Stu s){
printf("注意看这个女人叫%s,她的id是%d\n", s._name, s.id);
}
int main()
{
struct Stu student = { "小美", 1 };
Fun(student);
printf("注意看这个女人叫%s,她的id是%d\n", student._name, student.id);
return 0;
}
3.4 结构体指针充当函数参数
概念:形式参数是指向结构体变量的指针,意味着在参数传递时,由实际参数(结构体变量地址)
Fun1(&student); 传递给形式参数(结构体指针变量 struct Stu* pStu )。本质上就是地址传递过
程。
#include <stdio.h>
struct Stu
{
char _name[50];
int id;
};
void Fun1(struct Stu* pStu){
//pStu->id = 2;
(*pStu).id = 2;
}
int main()
{
struct Stu student = { "小美", 1 };
Fun1(&student);
printf("注意看这个女人叫%s,她的id是%d\n", student._name, student.id);
return 0;
}
结构体指针变量接收结构体变量的地址,
(*pStu).id = 2; 将 id 改成 2
四、结构体数组
4.1 概念
数组的每一个元素都是一个结构体变量。
4.2 语法
①声明
struct 结构体类型名 数组名[长度];
②初始化
五、共同体(联合体)
5.1 概念
一种复合数据类型,内部的成员变量共享同一块内存,即每一个数据成员的起始地址都相同,所有
数据成员占用同一段内存。修改一个数据成员就会影响其他数据成员的值。
结构体变量占用的内存大大于等于所有数据成员占用内存的总和,涉及字节对其问题。
共同体变量占用的内存大小等于最大的数据成员占用的内存大小,共同体使用了内存覆盖技术,同
一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来的成员的值覆盖掉。
5.2 语法
union 类型名 变量名;
#include <stdio.h>
union UN
{
int x;
char c;
};
int main()
{
union UN obj2;
printf("%d\n", sizeof(obj2));
}
所占内存大小:4字节
六、枚举
6.1 概念
将所有的数字一一列举出来并命名
目的:方便用户进行识别,提升代码的阅读性和可维护性
6.2 语法
①声明枚举类型
enum 类型名{值1=常量,值2,。。。值N};
②定义变量
enum 类型名 变量名 = 值
默认情况下枚举变量的值是从0开始的,且在赋值和使用时,只能使用枚举类型中出现的值
注:枚举类型没有++ --运算
#include<stdio.h>
enum week { Mon, Tues, Wed, Thurs = 100, Fri, Sat, Sun };
double Div(int x, int y)
{
if (y != 0)
{
printf("%lf\n", (double)x / y);
return OK;
}
else
{
return ERROR;
}
}
int main()
{
enum week weekday = Fri;
printf("%d\n", sizeof(weekday));
printf("%d\n", weekday);
}
枚举变量的大小,实质是常数所占内存空间的大小,上图代码,内存大小:4字节,运行结果如下
其中,枚举类型,第一个表示0,所以 Mon:0,Tues:1,Wed:2,其中Thurs = 100,后续的值依次+1,所以,Fri:101。