C语言系列(18)——结构体(01)
一、为什么需要结构体
若要定义一学生的一些特性,比如:姓名、年龄、性别、身高、体重
等,之前所学,只能用如下方式:
char name[10];
int age;
char sex;
float height;//身高
float weight;//体重
上面定义的这些数据,能表示一个人的一些属性
,但是这些变量之间不存在
任何的内在联系
,都是单独
存在的变量。如果这些特性更多,学生人数更多,很明显不好管理。
所以需要有一种数据类型
能把一个物体的多种属性
,结合在一起
,形成一个变量
,就好管理了。
二、什么是结构体
- 结构体:
使本没有任何内在关系的各数据类型,建立联系,整合成一个复合类型。
- 定义语法:
- 方式1:
struct
{
//成员变量
数据类型 变量名;
}s;
s为该结构体类型定义的变量,不推荐
使用这种方式。
- 方式二:
struct MyStruct
{
//成员变量
数据类型 变量名;
};
如,使用结构体,定于一个学生类型:
struct Student
{
//成员信息
char name[10];
int age;
char sex;
float height;
float weight;
};
该结构体定于完成后,struct Student
就是一个数据类型
,可以使用其定义变量:如
struct Student s;//使用struct Student类型定义了一个变量s
- 方式三:
typedef struct
{
char name[10];
int age;
char sex;
float height;//身高
float weight;//体重
}Student;
Student
就是一个数据类型
。可以使用其定义变量:如
Student s;//使用Student类型定义了一个变量s
注意: typedef
将一个类型另命名
,如:
typedef int INT_32; //将int 另命名为INT_32 。那用INT_32定义的变量等价于用int定义的变量。
int a;
INT_32 b;// 同 int b;
三种方式,很明显第三种
的使用频率是最高的,也是最方便的。
三、结构体变量的使用
以下示例,接上述结构体定义Student
- 结构体变量成员的赋值和取值:
- 成员运算符:“.”(点)
Student s;
s.age = 18;
s.sex = 'm';
s.height = 175;
s.weight = 70;
strcpy_s(s.name, sizeof(s.name), "Binson");
// strcpy(s.name, "Binson");
printf("name:%s\nsex:%c\nage:%d\nheight:%.2f\nweight:%.2f\n",
s.name, s.sex, s.age, s.height, s.weight);
打印结果:
name:Binson
sex:m
age:18
height:175.00
weight:70.00
- 成员运算符:“->”(用于指针变量操作成员)
Student *s;
s = (Student*)malloc(sizeof(Student));//需要动态分配内存
s->age = 18;
s->sex = 'm';
s->height = 175;
s->weight = 70;
strcpy_s(s->name, sizeof(s->name), "Binson");
// strcpy(s.name, "Binson");
printf("name:%s\nsex:%c\nage:%d\nheight:%.2f\nweight:%.2f\n",
s->name, s->sex, s->age, s->height, s->weight);
free(s);//注意释放
打印结果:
name:Binson
sex:m
age:18
height:175.00
weight:70.00
四、结构体字节数
结构体类型占用内存的字节大小
,很有讲究,而且也是考试和面试常出的题目,看如下案例:
- 示例1:
typedef struct
{
int year; //0~3 占用4个字节
int month; //4~7 占用4个字节
int day; //8~11 占用4个字节
}Date;//日期结构体
printf("%d\n", sizeof(Date));
打印结果:12
- 示例2:
typedef struct
{
int age; //0~3,占用4个字节
char sex; //4 占用1个字节
//补3个字节,最终大小为8个字节,为结构体成员中最大类型的倍数。
}Student;
printf("%d\n", sizeof(Student));
打印结果:8
- 示例3:
typedef struct
{
int age; //0~3,占用4个字节
char sex; //4,占用1个字节
//5~7 补3个字节。
double height; //8~15
}Student;
printf("%d\n", sizeof(Student));
打印结果:16
- 示例4:
typedef struct
{
int age; //0~3,占用4个字节
//需要与double对齐,补齐4~7 4个字节
double height; //8~15
char sex; //16~19
//补齐20~23,整字节数需要是最大成员字节数的倍数
}Student;
printf("%d\n", sizeof(Student));
打印结果:24
同样是表示同一个类型的结构体,因为成员排列不一致,大小也会不一样
。
- 示例5:
typedef struct
{
char name[10]; //0~9
char sex; //10~10。
//11~11 需与后面的int对齐,补齐1个字节
int age; //12~15
float height; //16~19
float weight; //20~23
}Student;
printf("%d\n", sizeof(Student));
打印结果:24
- 示例6:
typedef struct
{
char name[10]; //0~9
//需要与double对齐,补齐6字节 10~15
double age; //16~23
char sex; //24~27
float height; //28~31
float weight; //32~35
//36~39,需是最大成员double的倍数,补齐4字节
}Student;
printf("%d\n", sizeof(Student));
打印结果:40
- 规律:
1. 前面数据类型的总大小,要与后一个基础数据类型大小对齐,即能被后一个整除。(如不能则需补齐)
2. 总字节数大小是成员里最大基础数据类型字节数的整数倍。
注意: 结构体的成员排序方式,尽量从小到大排,可以节省内存空间。
练习:
1、定义一个结构体,描述一个公司,包括属性:公司名、法人代表、注册金额、公司地址等。
2、使用上述定义的公司结构体,定义一个普通变量和一个指针变量,分别对其属性赋值和取值。
3、自定义结构体,定义变量后分析其内存大小。