文章目录
前言
结构(structure) 是一种用户自定义的数据类型,用于存储多个不同类型的数据项
一、自定义类型:结构体
数组由数据类型相同的一系列元素组成;结构(structure)是一种用户自定义的数据类型,用于存储多个不同类型的数据项,在内存中连续存放
结构可以看作是另一种数组
1.声明结构体
结构体类型的声明就是告诉编译器结构布局,告诉编译器如何表示数据,但并不让编译器为数据分配空间
一般形式为:
struct 结构体名
{
数据类型 成员名1;
数据类型 成员名2;
...
数据类型 成员名n;//结构成员列表
};
例如,下面声明一个学生的结构:
struct Student
{
char name[20];//姓名
char sex[10];//性别
int age;//年龄
char id[20];//学号
};
2.定义结构体变量
一般形式为:
struct 结构体名 变量名;
例如,下面定义一个学生结构体的变量 s1:
struct Student
{
char name[20];//姓名
char sex[10];//性别
int age;//年龄
char id[20];//学号
};
struct Student s1;
- 表示创建了一个结构变量 s1,该变量的结构布局时 Student
- 编译器以结构布局 Student 为创建的结构变量 s1 分配空间
一般的定义结构体变量的三种方式
(1)在声明结构体后定义结构体变量
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
};
struct Student s1,s2,*p1;
(2)声明结构体的同时定义结构体变量
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
}s3,s4,*p2;
(3)省略结构体名定义结构体变量
struct
{
char name[20];
char sex[10];
int age;
char id[20];
}s5;
这种方法只能定义一次结构体变量,它是直接定义结构体变量
第三种定义与其它两种的类型是完全不同的,即使成员列表是一样的,若令 p2=s5,则是非法的
3.初始化
结构体变量定义时初始化
struct Stu s1={"Pit","M",18,"1234"};
//声明结构体后定义结构体变量并赋初值
#include<stdio.h>
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
};
struct Student s1 = { "Pit", "M", 18, "1234" };
int main()
{
printf("%s\t%s\t%d\t%s\n", s1.name, s1.sex, s1.age, s1.id);
//test
return 0;
}
//声明结构体的同时定义结构体变量并赋初值
#include<stdio.h>
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
}s1 = { "Pit", "M", 18, "1234" };
int main()
{
printf("%s\t%s\t%d\t%s\n", s1.name, s1.sex, s1.age, s1.id);
//test
return 0;
}
另外有指定初始化器,使用点运算符和成员名标识特定的元素
例如:只初始化Student结构的age成员:struct Student s1 = { .age = 20 };
也可以按照任意顺序使用指定初始化器,例如:
struct Student s1 = { .age = 20, .id = "1234", .sex = "M", .name = "Pit" };
(2)字符数组
4.字符串拷贝对结构体成员字符数组赋值
字符串拷贝: strcpy(成员,字符串)
(记得加头文件 #include<string.h>)
strcpy(s1.name, "Pit");
strcpy(s1.sex, "M");
strcpy(s1.id, "1234");
5.访问结构体成员
结构成员访问运算符 “.” 和 “->”
(1)“.”
一般形式:结构体变量名.成员名
例如:s1.name
(2)“->”
一般形式:结构指针变量->成员名
例如:ps1->name
#include<stdio.h>
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
};
struct Student s1 = { "Pit", "M", 18, "1234" };
int main()
{
struct Student* ps1 = &s1; //结构指针变量ps1指向结构体变量s1
printf("%s\n", s1.name);
printf("%s\n", (*ps1).name); //*ps1=s1
printf("%s\n", ps1->name);
}
二、typedef 定义结构体类型别名
一般形式为:
typedef struct 结构体名 别名;
typedef struct 结构体名//结构体名可以省略
{
//成员列表
}别名;
例如,下面定义学生结构体的别名 stu,然后定义结构体变量:
typedef struct Student//Student可以省略
{
char name[20];
char sex[10];
int age;
char id[20];
}stu;
stu s1,* p1;//直接用别名 stu 代替 struct Student
注意在C语言中,上例的用 typedef 起别名 stu 之后就不能以 struct Student s1 来声明结构变量了
上面的结构体名 Student 可以省略,原因是它并不是创建一个结构体变量,而是创建一个标签
注意typedef 起的别名的用法和 define 的简单的直接替换是有区别的
三、结构作为函数参数
#include <stdio.h>
#include <string.h>
struct Student
{
char name[20];
char sex[10];
int age;
char id[20];
};//结构体声明,不占用存储空间
void printStudent(struct Student s);
int main()
{
struct Student s1 = { 0 };//定义结构体变量 学生s1
/* 指定学生 s1 的信息 */
strcpy(s1.name, "Pit");
strcpy(s1.sex, "M");
s1.age = 18;
strcpy(s1.id, "1234");
/* 输出学生 s1 的信息 */
printStudent(s1);
return 0;
}
void printStudent(struct Student s)
{
printf("Student name: %s\n", s.name);
printf("Student sex: %s\n", s.sex);
printf("Student age: %d\n", s.age);
printf("Student id: %s\n", s.id);
}
另外,上面打印学生信息的函数 printStudent 可以改为地址传参的形式:
void printStudent(const struct Student* p)
//(const在*左边,表示指针指向的内容不能通过指针来改变)
{
printf("Student name: %s\n", p->name);
printf("Student sex: %s\n", p->sex);
printf("Student age: %d\n", p->age);
printf("Student id: %s\n", p->id);
}
结构体地址传参相比于结构体传参更好
原因是,函数传参的时候,参数是需要压栈的,会有时间和空间的系统开销;如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,这就会导致性能的下降