结构体
数组是存储相同数据类型变量的集合,但是无法存储不同数据类型的变量。
比如,存放学生的名字+年龄+性别+学号
这几项信息,就无法实现。
那么C语言为了解决这个问题就有了结构体的概念。
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
结构体的定义
struct tag
{
member-list;
...
}variable-list;
struct:struct是关键字,定义结构体,必须使用 struct 语句
tag:结构体的标识符
member-list:结构体的成员变量
variable-list:结构体变量,您可以指定一个或多个结构体变量,这是一个全局变量(可以不写,不写的话这里就是声明结构体)
代码示例
struct Stu {
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
//上面只是声明结构体
struct Books
{
char title[50];//标题
char author[50];//作者
char subject[100];//主题
int book_id;//编号
} book;//声明类型的同时定义变量book,这里是全局变量
int main()
{
//定义struct Stu类型变量
struct Stu stu;
//定义struct Books类型变量
struct Books book1;
return 0;
}
特殊的结构体定义
在声明结构的时候,可以不完全的声明。
//此结构体没有标识符,是一个匿名结构体
struct
{
int a;
char b;
double c;
}s1;//声明类型的同时定义变量s1
struct
{
int a;
char b;
double c;
} *p1;//声明类型的同时定义变量*p1
//使用typedef创建新类型,my_struct代表struct s2这个类型
typedef struct s2
{
int a;
char b;
double c;
} my_struct;
//结构体嵌套
struct Point
{
int x;
int y;
};
struct Node
{
int data;
struct Point p;//结构体的成员变量是结构体
struct Node* next;
};
int main()
{
//这两个匿名结构体虽然成员变量一样,但是编译器会把它们看成是不同的类型
*p1 = &s1; //错误
//定义使用typedef创建的新类型my_struct
my_struct s3;
return 0;
}
结构体的初始化
和其它类型变量一样,对结构体变量可以在定义时指定初始值。
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} book = { "C 语言", "Aping", "编程语言", 123456 };
struct Stu {
char name[20];
int age;
char sex[5];
char id[20];
};
struct Stu stu1 = { "张三",18,"男","10086" };
//匿名结构体
struct
{
int a;
char b;
double c;
}s1;
s1 = { 8,'a',3.14 };
//结构体嵌套
struct Point
{
int x;
int y;
};
struct Node
{
int data;
struct Point p;
struct Node* next;
};
struct Node node1 = { 88,{6,9},NULL };
访问结构体成员变量
我们可以使用**成员访问运算符(.)**访问结构的成员变量
也可以使用->
符号通过结构体的指针访问结构的成员变量
代码示例
struct Stu {
char name[20];
int age;
char sex[5];
char id[20];
};
int main()
{
struct Stu stu1 ;
strcpy(stu1.name, "张三");
stu1.age = 18;
strcpy(stu1.sex, "男");
strcpy(stu1.id, "123456");
//使用成员访问运算符(.)访问结构的成员变量
printf("%s\n", stu1.name);
printf("%d\n", stu1.age);
printf("%s\n", stu1.sex);
printf("%s\n", stu1.id);
//使用->符号通过结构体的指针访问结构的成员变量
struct Stu* ps = &stu1;
printf("%s\n", ps->name);
printf("%d\n", ps->age);
printf("%s\n", ps->sex);
printf("%s\n", ps->id);
return 0;
}
结构体作为参数传参
struct Stu {
char name[20];
int age;
char sex[5];
char id[20];
};
void Stu_printf(struct Stu stu)
{
printf("%s\n", stu.name);
printf("%d\n", stu.age);
printf("%s\n", stu.sex);
printf("%s\n", stu.id);
}
void Stu_printf_p(struct Stu* ps)
{
printf("%s\n", ps->name);
printf("%d\n", ps->age);
printf("%s\n", ps->sex);
printf("%s\n", ps->id);
}
int main()
{
struct Stu stu1;
strcpy(stu1.name, "张三");
stu1.age = 18;
strcpy(stu1.sex, "男");
strcpy(stu1.id, "123456");
//结构体作为参数传参
Stu_printf(stu1);
//结构体指针作为参数传参
struct Stu* ps = &stu1;
Stu_printf_p(ps);
return 0;
}
结构体内存对齐(计算结构体大小)
结构体的对齐规则:
第一个成员在与结构体变量偏移量为0的地址处。
其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数:编译器默认的一个对齐数与该成员类型大小的较小值。(VS中默认的值为8)
结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
代码示例1
struct S1
{
char c1;
int i;
char c2;
double d;
};
int main()
{
printf("%d\n", sizeof(struct S1));// 24
return 0;
}
代码示例2
struct S2
{
char c1;
char c2;
int i;
double d;
};
int main()
{
printf("%d\n", sizeof(struct S2));//16
return 0;
}
我们发现共用体S1和S2的成员变量是一样的,但是所占的空间不一样
造成这样的问题是因为S1和S2的成员变量的位置不一样
所以为了节省空间,我们要让占用空间小的成员尽量集中放在一起
代码示例3
struct S2
{
char c1;
char c2;
int i;
double d;
};
//结构体嵌套问题
struct S3
{
char c1;
struct S2 s2;
double d;
};
int main()
{
printf("%d\n", sizeof(struct S3));// 32
return 0;
}
本文出现任何错误,欢迎留言批评指正。