1.结构体的声明
1.1 结构的基础知识
结构是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。
结构是一种集合(每个成员类型可以不同)
数组是一种相同类型元素的集合
内置类型:char short int long long long float double
复杂对象:
人:名字 电话 性别 身高
书:书名 作者 定价 书号
结构的作用:内置类型表示的对象有限 描述复杂对象使用结构体
1.2 结构的声明
结构体关键字+ 结构体标签(创建出的结构体类型名 ) 成员列表(多个成员变量) 变量列表(用结构体类型创建的结构体变量);
//声明的结构体类型 struct Peo
/*struct Peo//结构体类型
{
char name[20];
char tele[12];//字符串\0
char sex[5]; //女 男 保密一个汉族占两个字节 字符串\0
int high;
}p1,p2; */ //结构体类型声明 创建了结构体类型
//结构体类型声明时,变量列表可有可无
//p1和p2是使用struct Peo这个结构体类型创建的2个变量
//放在main(){}外面定义,是两个全局的结构体变量(少用)
//通常还是不在main(){}外部定义
//在main()内部声明的结构体类型只能在main()内部使用有范围限制 一般都外部声明
struct Peo//结构体类型
{
char name[20];
char tele[12];
char sex[5];
int high;
};
int main()
{
struct Peo p1;//结构体变量的创建
return 0;
}
//结构体类型声明不占空间 去使用类型去创建结构体变量才会向内存申请空间
1.3 结果成员的类型
结构的成员可以是标量(int float double),数组,指针,甚至是其他结构体
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
struct St
{
struct Peo p;//结构体内部嵌套了一个结构体
int num;
float f;
};
1.4 结构体变量的定义和初始化
结构体变量的定义:
//结构体变量的创建
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
}p3,p4;
struct Peo p5,p6;//全局变量(main()的{}外)p3p4p5p6
int main()
{
struct Peo p1 = {0};//局部变量 p1
return 0;
}
结构体变量的初始化:创建结构体变量的同时给它一个值
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
int main()
{
struct Peo p1 = {"张三","15596667878","男",181};//初始化
return 0;
}
嵌套结构体的初始化:
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
struct St
{
struct Peo p;//结构体内部嵌套了一个结构体
int num;
float f;
};
int main()
{
struct Peo p1 = {"张三","15596668862","男",181};//初始化
struct St s = {{"lisi","15596668888","女",166},100,3.14};
//嵌套结构体初始化
//放不止一个成员用{} 嵌套在内部的结构体用{}
printf("%s %s %s %d\n",p1.name,p1.tele,p1.sex,p1.high);
printf("%s %s %s %d %d %f\n",s.p.name,s.p.tele,s.p.sex,s.p.high,s.num,s.f);
return 0;
}
注意:
- 浮点数在内存中不能精确保存
- 结构体初始化可以不完全初始化
2.结构体成员的访问
结构体变量.成员变量 结构体指针->成员变量
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
struct St
{
struct Peo p;//结构体内部嵌套了一个结构体
int num;
float f;
};
void print2(struct Peo* sp)
{
printf("%s %s %s %d\n",sp->name,sp->tele,sp->sex,sp->high);
//结构体指针->成员变量
}
void print1(struct Peo p)
{
printf("%s %s %s %d\n",p.name,p.tele,p.sex,p.high);
//结构体变量.成员变量
}
int main()
{
struct Peo p1 = {"张三","15596668862","男",181};//初始化
struct St s = {{"lisi","15596668888","女",166},100,3.14};
//嵌套结构体初始化
//放不止一个成员用{} 嵌套在内部的结构体用{}
printf("%s %s %s %d\n",p1.name,p1.tele,p1.sex,p1.high);
printf("%s %s %s %d %d %f\n",s.p.name,s.p.tele,s.p.sex,s.p.high,s.num,s.f);
print1(p1);
print2(&p1);
return 0;
}
3.结构体传参
struct Peo
{
char name[20];
char tele[12];
char sex[5];
int high;
};
void print2(struct Peo* sp)
{
printf("%s %s %s %d\n",sp->name,sp->tele,sp->sex,sp->high);
//结构体指针->成员变量
}
void print1(struct Peo p)
{
printf("%s %s %s %d\n",p.name,p.tele,p.sex,p.high);
//结构体变量.成员变量
}
int main()
{
struct Peo p1 = {"张三","15596668862","男",181};
printf("%s %s %s %d\n",p1.name,p1.tele,p1.sex,p1.high);
//结构体变量的打印一般通过函数传参打印
print1(p1);
print2(&p1);
return 0;
}
传参:1结构体变量 2结构体变量的地址,两种传参方式都能打印输出,区别?
1.传值,即结构体变量时,形参p会创建一块跟实参p1一样的空间,(实参传值给形参,形参是实参的一份临时拷贝)传参时数据也会拷贝一份到形参,形参开辟一块空间会造成空间的浪费,数据拷贝也会需要时间,造成时间的浪费,所以进行结构体对象的传参,会造成空间和时间的双重浪费,导致性能下降。
2.传址,即结构体变量的地址时,形参部分只需要创建一个指针变量的大小(4/8byte),通过指针sp可以找到main()中创建的结构体变量p1,打印时找到main()中p1变量的数据进行打印。(函数压栈 系统开销比较小 4/8byte 性能比较高 )
函数传参时,参数是需要压栈的;如果传递一个结构体对象时,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降
结论:结构体传参时,尽量去传结构体地址