C语言定义了很多基本数据类型,当我们需要为某一变量定义多个不同的数据类型时,我们就用到了结构体。
结构体可以作为一个变量存放多个不同数据类型的数据,而数组只能存放同数据类型的多个数据。
比如一本书:具有图书名称,图书作者,图书售价,出版日期,出版社,ISBN号。
基本结构:
struct 结构体名称
{ 结构体成员1; 结构体成员2; 结构体成员3; ...... };
其中的结构体成员可以是一种基本的数据类型也可以是数组或者另一个结构体。
结构体的声明:
将书本的各个数据整合成为结构体的声明就如下:结构体名称通常大写字母开头。
struct Book
{
char title[128];
char author[40];
float price;
unsigned int date;
char publishter[40];
};
注意,以上为结构体的声明,并不会在在内存中真正的申请空间,我们需要对结构体定义才能使用结构体。
定义结构体类型变量: struct 结构体名称 结构体变量名
结构体的定义:
#include <stdio.h>
//声明结构体
struct Book
{
char title[128];
char author[40];
float price;
unsigned int date;
char publisher[40];
};
struct Bookk
{
char title[128];
char author[40];
float price;
unsigned int date;
char publisher[40];
}bookk;//这里的bookk也为定义结构体,函数外的定义为全局变量
int main(void)
{
//定义结构体,若放在函数里定义,那么结构体为只属于函数的局部变量
struct Book book;
}
两种定义方式,区别在于作用域不同。
访问结构体变量:
点号运算符:(.)--->比如book.title就是引用book结构体的title的成员,它是一个字符数组,而book.price则是引用book结构体的price成员,它是一个浮点型的变量。
#include <stdio.h>
//声明结构体
struct Book
{
char title[128];
char author[40];
float price;
unsigned int date;
char publisher[40];
} book;//这里的book也为定义结构体,函数外的定义为全局变量
int main(void)
{
printf("请输入书名:");
scanf("%s", book.title); //引用时为book.title
printf("请输入作者:");
scanf("%s", book.author);
printf("请输入售价:");
scanf("%f", &book.price);
printf("请输入出版日期:");
scanf("%d", &book.date);
printf("请输入出版社:");
scanf("%s", book.publisher);
printf("书名:%s\n",book.title);
printf("作者:%s\n", book.author);
printf("售价:%f\n", book.price);
printf("出版日期:%d\n", book.date);
printf("出版社:%s\n", book.publisher);
return 0;
}
初始化结构体变量:
初始化结构体变量与初始化变量与数组一样,都是在定义时就为其赋值。注意类型对号入座。
struct Book book = {
"《C语言》",
"abc",
99.9,
19721010,
"出版社"
};
既然在结构体定义时就可以赋值,以下也是正确的赋值方式。
struct Book
{
char title[128];
char author[40];
float price;
unsigned int date;
char publisher[40];
} book = {
"《C语言》",
"abc",
99.9,
19721010,
"出版社"
};
也可以使用(.)运算符初始化指定成员,可以不按顺序。
//初始化指定结构体成员
struct Book book = {
.author = "abc",
.price = 99.9
};
结构体的内存对齐:
对结构体变量的成员进行数据读取时,编译器为方便快速读取,会对结构体成员进行内存对齐,会导致占用空间加大。
比如 char-int-char所占内存字节为1-4-1,编译器为方便快速读取,使每个成员数据内存强行相等,32位系统常对其为4字节,使内存分布为4-4-4,总共占用12字节。其实对齐后的内存空间只有第一个字节存储char类型的数据,其余三字节为空,第三个同理。为避免内存对齐造成内存浪费,所以我们对结构体声明和定义成员变量时,可以变为char-char-int,这样前两个char对齐时共用一个对齐后的四字节内存,虽然有两个字节浪费,相比之前也避免了浪费。