太晚了(11点半了),明天继续结构体
数组: 是用于保存一组相同类型的数据
结构体: 是用于保存一组不同类型的数据
// 1.定义结构体类型
struct Person
{
// char name[20];
char *name;
int age;
double height;
};
// 2.定义结构体变量
// int num;
struct Person p;
// 注意: 数组不能先定义再进行一次性的初始化, 所有下面的写法是错误的
// p.name = "lnj"; // name = {'l', 'n', 'j', '\0'};
// 可以使用 结构体变量名称.属性的方式给结构体变量赋值
p.name = "lnj";
p.age = 30;
p.height = 1.75;
结构体的初始化
struct Dog
{
char *name;
int age;
double height;
};
// 1.定义的同时初始化
struct Dog sd = {"wc", 13, 5.0};
// 2.先定义再初始化(逐个初始化)
struct Dog sd1;
sd1.name = "ww";
sd1.age = 5;
sd1.height = 10.9;
// 3.先定义再初始化(一次性初始化)
struct Dog sd2;
// 特别注意: 结构体和数组有一点区别, 数组不能先定义再进行一次性的初始化, 而结构体可以
// 只不过需要明确的告诉系统{}中是一个结构体
sd2 = (struct Dog){"xq", 8, 8.8}; // 数组? 结构体?
// 4.指定将数据赋值给指定的属性
struct Dog sd3 = {.height = 1.77, .name = "ww", .age = 33};
printf("name = %s, age = %i, height = %lf\n", sd3.name, sd3.age, sd3.height);
结构体如何开辟存储空间
其实结构体分配存储空间本质上并不是将所有属性占用的存储空间的总和加在一起后再分配。
而是会获取结构体类型中占用内存最大的属性的大小, 然后取该大小的倍数。
如果剩余的存储空间"不够"存储将要存储的数据, 那么就会重新开辟8个字节的存储空间, 并且将需要存储的数据放到新开辟的存储空间中。
如果剩余的存储空间"够"存储将要存储的数据, 那么就不会开辟了。
struct Person{
// double height; // 8
int age; // 4
// int heigth; // 4
double height; // 8
char c; // 1
// char *name; // 8
};
struct Person sp;
printf("size = %lu\n", sizeof(sp));
输出:
size = 24
结构体定义的形式
1.先定义结构体类型, 在定义结构体变量
struct Person
{
int age;
char *name;
double height;
};
struct Person sp;
2.定义结构体类型的同时定义结构体变量
struct Person
{
int age;
char *name;
double height;
} sp;
3.定义结构体类型的同时定义结构体变量, 并且省略结构体名称
弊端: 由于结构体类型没有名称, 所以以后就不能使用该结构体类型
优点: 如果结构体类型只需要使用一次, 那么可以使用该方式
struct
{
int age;
char *name;
double height;
} sp;
结构体类型的作用域
如果将结构体类型写在函数或者代码块外面, 那么结构体类型的作用域和全局变量一样, 从定义的那一行开始一直直到文件末尾。相同作用域不能有同名的结构体类型。
在不同的作用域中可以定义同名的结构体类型 , 如果使用同名的结构体类型定义结构体变量, 采用就近原则。
如果结构体定义在函数或者代码块中, 那么结构体类型的作用域和变量的作用域一样, 从定义的那一行开始, 一直到函数结束或者到代码块结束。
指向结构体的指针
当指针指向结构体之后如何利用指针访问结构体
结构体变量名称.属性;
(*结构体指针变量名称).属性;
结构体指针变量名称->属性;
struct Person
{
int age;
char *name;
double height;
};
struct Person sp = {30, "lnj", 1.75};
sp.name = "lnj";
sp.age = 30;
sp.height = 1.75;
// 定义了一个指向结构体的指针
// *sip == sp
struct Person *sip;
sip = &sp;
// 注意: 报错的原因是因为.运算符的优先级比*高
(*sip).name = "xxx";
(*sip).age = 88;
(*sip).height = 1.95;
printf("age = %i, name = %s, height = %lf\n", (*sip).age, (*sip).name, (*sip).height);
sip->age = 99;
sip->name = "oooo";
sip->height = 2.1;
printf("age = %i, name = %s, height = %lf\n", sip->age, sip->name, sip->height);
结构体数组
// 要求定义变量保存公司中所有部门的绩效
struct Bumen
{
char *name;
int count;
double kpi;
};
struct Bumen ios = {"iOS", 20, 100.0};
struct Bumen andorid = {"Andoird", 10, 99.0};
struct Bumen php = {"php", 500, 88.0};
// 元素类型 数组名称[元素个数];
struct Bumen bumens[3] =
{
{"iOS", 20, 100.0}, // 0
{"Andoird", 10, 99.0},
{"php", 500, 88.0}
};
// bumens[0] == ios
bumens[0].name = "iOSv587";
bumens[0].count = 99;
bumens[0].kpi = 100.0;
printf("name = %s, count = %i, kpi = %lf\n", bumens[0].name, bumens[0].count, bumens[0].kpi);
结构体嵌套
如果结构体的属性又是一个结构体, 那么可以通过连续.的方式, 访问结构体属性中的属性。
如果结构体类型中的属性又是一个结构体, 那么赋值时候通过{}赋值。
struct Person
{
int age;
char *name;
// 出生日期
struct Date birth;
// 出生时间
// struct Date time;
// struct Time shic;
// 小学入学时间
struct Date ruxue;
// 小学毕业时间
struct Date biye;
// ....
};
struct Person sp =
{
30,
"lnj",
{
1980,
1,
15,
{
15,
12,
8
}
},
{
1990,
6,
9
},
{
1996,
9,
5
}
};
结构体与函数
#include <stdio.h>
struct Person
{
int age;
char *name;
};
void change(struct Person *p);
int main(int argc, const char * argv[]) {
struct Person sp1 = {30, "lnj"};
printf("sp1.age = %i\n", sp1.age);
change(&sp1);
printf("sp1.age = %i\n", sp1.age);
return 0;
}
void change(struct Person *p)
{
p->age = 998;
}
输出:
sp1.age = 30
sp1.age = 998