目录
1.结构体的声明
1.1 结构体的基础知识
什么是结构体?
知识点1:
我们为什么要用到结构体,我们都已经学了很多int char …等类型还学到了同类型元素构成的数组,以及取上述类型的指针,在一些小应用可以灵活使用,然而,在我们实际应用中,每一种变量进行一次声明,再结合起来显然是不太实际的,类如一位学生的信息管理,他可能有,姓名(char),学号(int)成绩(float)等多种数据。如果把这些数据分别单独定义,就会特别松散、复杂,难以规划,因此我们需要把一些相关的变量组合起来,以一个整体形式对对象进行描述,这就是结构体的好处。
官方来说结构体就是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。说到集合,数组也是集合,但是不同的是数组只能是相同类型元素的集合。
结构体可以将不同类型的数据-----整形(int, long, ......),浮点数(float, double),字符型(char)存放在一起,作为一个整体进行处理,使得C语言有能力描述复杂类型。
1.2 结构体的声明
知识点2:
结构体类型的声明:
struct tag
{
member1;
member2;
} variable-list;
解释:
▶ struct是结构体关键字
▶ tag是结构体的标签名,是自定义的
▶ struct tag就是结构体类型
▶ {}里面放的是成员列表
▶ variable-list是变量▶ member1 , member2 是结构体成员
▶结构体成员的定义方式与变量和数组的定义方式相同
▶结构体成员,只是不能初始化。
例如描述一个学生:
typedef struct Stu{char name [ 20 ]; // 名字int age ; // 年龄char sex [ 5 ]; // 性别char id [ 20 ]; // 学号} Stu; // 分号不能丢
1.3 结构体成员的类型
结构体成员可以是标量、数组、指针,甚至是其他结构体。
1.4 结构体变量的定义和初始化
有了结构体类型,那如何定义变量,其实很简单。
struct Point{int x ;int y ;} p1 ; // 声明类型的同时定义变量 p1struct Point p2 ; // 定义结构体变量 p2// 初始化:定义变量的同时赋初值。struct Point p3 = { x , y };struct Stu // 类型声明{char name [ 15 ]; // 名字int age ; // 年龄};struct Stu s = { "zhangsan" , 20 }; // 初始化struct Node{int data ;struct Point p ;struct Node * next ;} n1 = { 10 , { 4 , 5 }, NULL }; // 结构体嵌套初始化struct Node n2 = { 20 , { 5 , 6 }, NULL }; // 结构体嵌套初始化
2.结构体成员的访问
- 结构体变量访问成员
s有成员name和age;
我们可以通过变量或变量的地址去访问s的成员。
struct S s;strcpy(s.name, "zhangsan"); // 使用 . 访问 name 成员s.age = 20; // 使用 . 访问 age 成员
struct Stu{char name [ 20 ];int age ;};void print ( struct Stu * ps ){printf ( "name = %s age = %d\n" , ( * ps ). name , ( * ps ). age );// 使用结构体指针访问指向对象的成员printf ( "name = %s age = %d\n" , ps -> name , ps -> age );}int main (){struct Stu s = { "zhangsan" , 20 };print ( & s ); // 结构体地址传参return 0 ;}
我们也可以通过指针访问结构体, (*ps).name。
为什么结构体会有两种访问方式?
在函数传参(传值,传址)时,会生成临时变量,如果要传的结构体变量太大的话,传值拷贝出来的临时变量对象会很大,如果用传址的方式来传结构体变量地址的话,可以很好的节省空间。
3. 结构体传参
看代码:
struct S{int data [ 1000 ];int num ;};struct S s = {{ 1 , 2 , 3 , 4 }, 1000 };// 结构体传参void print1 ( struct S s ){printf ( "%d\n" , s . num );}// 结构体地址传参void print2 ( struct S * ps ){printf ( "%d\n" , ps -> num );}int main (){print1 ( s ); // 传结构体print2 ( & s ); // 传地址return 0 ;}
函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
结论:结构体传参的时候,要传结构体的地址。 (传地址效率高!)
补充:
1. C++中struct 与 class 的区别
class成员的默认权限为private,struct成员的默认权限为public.
class的继承默认是private继承,struct的继承默认是public继承。
class可以作为一个关键字定义模板参数(与typename作用一样),而struct不可以。
2. C和C++结构体的区别
1.C++结构体内部可以有成员变量和成员函数,而C中结构体只能有成员变量。
2.C结构体的成员变量不能在声明时给初值,而C++中可以。
3.C++中定义结构体变量时,可以不在名称前面加上struct关键字,而C一定要。
4.C结构体内不能有静态成员,而C++可以。
5.C结构没有访问修饰限定符,而C++有。