目录
一、什么是结构体
结构体是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
与结构体类似的是数组,数组是相同类型元素的集合。
结构体的作用:描述生活中一些复杂的对象。
例如:
- 描述一个人:这个人的姓名、性别、年龄、电话……
- 描述一本书:这本书的书名、作者、出版社、定价……
二、结构体的声明
struct tag
{
member - list;
}variable - list;
- struct:结构体关键字。
- tag:结构体标签名。(标签名可以自定义)
- member - list:成员列表。(大括号中可以有多个成员列表)
- variable - list:变量列表。(变量列表后必须有分号,多个变量之间使用逗号隔开)
三、结构体成员的类型
结构体的成员可以是变量、数组、指针,甚至是其他结构体。
struct Stu1
{
char name[20];
int age;
float score;
};
struct Stu2
{
char name[20];
int age;
struct Stu1 s1;
float score;
struct Stu1* next; //定义结构体类型的指针
};
四、结构体变量的定义和初始化
1、结构体变量的定义
有两种方式:
- 直接写在结构体后面,多个变量之间用逗号间隔,以分号结束。这种结构体变量是全局结构体变量。
- 在main函数中创建结构体变量,结构体类型为结构体关键字+结构体标签名。这种结构体变量是局部结构体变量。
举例:声明一个学生的结构体类型
struct Stu
{
char name[20];
int age;
float score;
};//如果不写结构体变量也要加分号
(1)创建全局结构体变量
struct Stu
{
char name[20];
int age;
float score;
}s1,s2;//声明类型的同时定义s1,s2两个全局的结构体变量
struct Stu s3;//定义结构体全局变量s3
(2)创建局部结构体变量
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
//类型:struct Stu
//变量名:s4
struct Stu s4;//定义一个局部的结构体变量
return 0;
}
2、结构体变量初始化
定义变量的同时赋初值
(1)全局结构体变量初始化
struct Stu
{
char name[20];
int age;
float score;
}s1 = { "张三",20,80.5f }, s2 = {"李四",21,89.6f};
struct Stu s3 = {"王五",19,95.5f};//不写 f 默认为double类型
(2)局部结构体变量初始化
struct Stu
{
char name[20];
int age;
float score;
};
int main()
{
struct Stu s4= { "张三",22,88.5f };//不写 f 默认为double类型
}
(3)结构体嵌套初始化
struct Point
{
int x;
char c;
}p1;
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = { 10, {4,'a'}, NULL }; //结构体嵌套初始化
struct Node n2 = { 20, {5, 'b'}, NULL };//结构体嵌套初始化
int main()
{
struct Node n3 = { 30, {9, 'c'}, NULL };
return 0;
}
五、结构体成员访问
1、结构体变量访问成员
结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。
struct Stu
{
char name[20];
int age;
float score;
}s1 = { "张三",20,80.5f }, s2 = {"李四",21,89.6f};
struct Stu s3 = {"王五",19,95.5f};//不写 f 默认为double类型
int main()
{
struct Stu s4 = { "丽丽", 22, 88.5f };
printf("姓名:%s 年龄:%d 成绩:%.1f\n", s1.name, s1.age, s1.score);
printf("姓名:%s 年龄:%d 成绩:%.1f\n", s2.name, s2.age, s2.score);
printf("姓名:%s 年龄:%d 成绩:%.1f\n", s3.name, s3.age, s3.score);
printf("姓名:%s 年龄:%d 成绩:%.1f\n", s4.name, s4.age, s4.score);
return 0;
}
运行结果
2、结构体指针访问指向变量的成员
有时候得到的不是一个结构体变量而是指向一个结构体的指针,结构体指针通过(->)访问的。
struct Stu
{
char name[20];
int age;
float score;
};
void Print(struct Stu* ps)
{
printf("姓名:%s 年龄:%d 成绩:%.1f\n", (*ps).name, (*ps).age, (*ps).score);
printf("姓名:%s 年龄:%d 成绩:%.1f\n", ps->name, ps->age, ps->score);
}
int main()
{
struct Stu s1 = { "张三", 22, 88.5f };
Print(&s1);
return 0;
}
运行结果
3、结构体成员嵌套的访问
struct Point
{
int x;
char c;
}p1;
struct Node
{
int data;
struct Point p;
}n1 = { 10, {4,'a'}}; //结构体嵌套初始化
int main()
{
struct Node n2 = { 30,{9,'b'}};
printf("%d %d %c\n", n1.data, n1.p.x, n1.p.c);
printf("%d %d %c\n", n2.data, n2.p.x, n2.p.c);
return 0;
}
运行结果
六、结构体传参
1、结构体传参,传递结构体对象(传值)
struct S
{
int arr[100];
double n;
char ch[50];
};
void Print1(struct S tmp)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", tmp.arr[i]);
}
printf("\n");
printf("%.2lf\n", tmp.n);
printf("%s\n", tmp.ch);
}
int main()
{
struct S s1 = { {1,2,3,4,5,6,7,8,9,10},3.14,"Hello" };
Print1(s1);
return 0;
}
运行结果
2、结构体传参,传递结构体的地址(传址)
struct S
{
int arr[100];
double n;
char ch[50];
};
void Print2(struct S* ps)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
printf("%.2lf\n", ps->n);
printf("%s\n", ps->ch);
}
int main()
{
struct S s1 = { {1,2,3,4,5,6,7,8,9,10},3.14,"Hello" };
Print2(&s1);
return 0;
}
运行结果
Print1与Print2,选择Print比较好,因为:
函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。
结论: 结构体传参的时候,要传结构体的地址。
七、总结
介绍了C语言中结构体的一些基本内容,后期会继续介绍结构体的其他内容。