结构体
结构体变量开辟空间会从大的地址端开始开辟,给成员开辟空间从小的地址端开始开辟。
结构体占用的总的内存大小是其所有成员中占用空间最大的成员所用内存的倍数。
结构体虽然是构造类型,但是结构体之间赋值是值传递,所以传递给函数时,函数内部的修改不会影响原有结构体。
结构体定义模版:
struct 结构体名{
类型名1 成员名1;
类型名2 成员名2;
类型名3 成员名3;
...
类型名n 成员名n;
};//定义结构体
struct 结构体名 结构体变量名;//定义结构体变量
struct [结构体名]{
类型名1 成员名1;
类型名2 成员名2;
类型名3 成员名3;
...
类型名n 成员名n;
} 结构体变量名;//定义结构体的同时定义变量,这时结构体的名字可以省略,但是这种结构体类型不能复用
结构体可以定义在函数内,也可以定义在函数外,定义在函数内只能局部使用。
访问结构体成员有三种方式:
- 结构体变量名.成员名
- (*指针变量名).成员名
- 指针变量名->成员名
#include <stdio.h>
struct Student {
char *name;
int age;
};
void printStu(struct Student student);
int main() {
struct Student stu = {"qianyi", 26};//按照定义的成员顺序初始化
printf("stu:\n");
printStu(stu);
stu = (struct Student) {.age=35, .name="suixin"};//也可以定义之后再初始化或者修改值,可以不按顺序
printf("stu:\n");
printStu(stu);
struct Student stu1 = {.age=35, .name="suixin"};//定义的同时不按顺序进行初始化,不按顺序需要写成员名
printf("stu1:\n");
printStu(stu1);
stu.name = "qianyi";//修改单个成员值或初始化单个值
stu.age = 27;
printf("stu:\n");
printStu(stu);
struct Student stu3[2] = {"suixin", 18, "qianyi", 25};
struct Student stu4[2] = {{"suixin", 18},
{"qianyi", 25}};
printf("stu3[]:\n");
for (int i = 0; i < sizeof stu3 / sizeof(struct Student); i++) {
printStu(stu3[i]);
}
printf("stu4[]:\n");
for (int i = 0; i < sizeof stu4 / sizeof(struct Student); i++) {
printStu(stu4[i]);
}
struct Student *p = &stu1;
printf("stu1:\n");
printStu(*p);
/**
* 访问结构体成员有三种方式:
* 结构体变量名.成员名
* (*指针变量名).成员名
* 指针变量名->成员名
*/
printf("stu1.name is:%s\n", (*p).name);
printf("stu1.name is:%s\n", p->name);
}
void printStu(struct Student student) {
printf("name:%s,age:%d\n", student.name, student.age);
}
结构体内存分配:
#include <stdio.h>
int main() {
struct StructB {
char *str;//8字节
int a1;//4字节
int a2;
int a3;
char c1;//1字节
};
struct StructA {
struct StructB b;//24字节
struct StructA *s1;//8字节
};
struct StructA a;
/**
* 注意:
* 结构体A中不可以嵌套结构体A的变量,因为自身大小不确定,
* 但是可以嵌套自身类型的指针变量,或者嵌套其他结构体类型变量
* 内存分配:
* 结构体A中嵌套结构体B,可以把结构体B中的成员都放结构体A中计算:
* int总共12字节,char总共1字节,占用空间最大的成员是指针变量,占用8字节,有两个指针变量
* 既比13大,又是8的最小倍数的数字是16,所以16+8*2为32字节
*/
printf("%i\n", sizeof a);//32字节
printf("%i\n", sizeof(struct StructA));//32字节
}
共用体
#include <stdio.h>
int main() {
union Test {
int age;
char ch;
};
/*
* 共用体中的所有成员共享一个内存空间,所以不可以同时存取各自的值
* 使用场景:
* 1. 需要大量的临时变量,并且这些变量的类型不同,会随时更换
* 2. 有两个很长的数据结构,但是不会同时使用
* 3. 通信的数据包,因为不知道对方会发送什么样的数据包过来,所以定义几种格式的包,收到包之后根据包的格式取出数据。
*/
union Test t;
printf("%i\n", sizeof t);//4字节
printf("%i\n", sizeof(union Test));//4字节
t.age = 33;
printf("t.age=%i\n", t.age);
t.ch = 'a';
printf("t.ch=%c\n", t.ch);//a
printf("t.ch=%i\n", t.ch);//97
printf("t.age=%i\n", t.age);//97
}
枚举类型
枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。
定义枚举类型变量可以参考定义结构体类型变量。
#include <stdio.h>
int main() {
enum Season {
Spring, Summer, Autumn, Winter
};
enum Season s;
s = Spring;//等价于s=0
printf("%d\n", s);//0
s = 3;//等价于s=Winter;
printf("%d\n", s);//3
/**
* 默认情况下,第一个枚举元素的值为0,第二个为1,...
* 也就是说Spring的值为0,Summer的值为1,...
*/
}