c语言中用struct来标识定义的结构体类型,结构体是一些值的集合,这里的值可以是不同内置类型的,这些值称为成员变量
内置类型**char ,short ,int ,long ,float ,double, long long。**
结构题是一种构造类型,其他构造类型:联合体,枚举。
例如这里定义一本书,需要包括名字,作者和价格
c语言中引用结构体成员可以用.或者->来引用成员变量
#include<stdio.h>
#include<stddef.h>
struct Book
{
//成员变量
char name[20];//书名
char author[20];//作者名字
short price;//价格
}b2,b3,b4;//每一本书的名字
int main()
{
struct Book b1 = { "c语言程序设计", "谭浩强", 55 };//结构体的初始化
printf("%s %s %d\n", b1.name, b1.author, b1.price);//打印结构体
return 0;
}
结构体的声明
struct S
{
member-list;//成员列表,如上文的书名,价格,作者等
}variable-list;//变量列表,如上文的b1,b2,b3
这里在结构体定义时创建了一个s,下方在使用这个结构体时可以不使用s,而是重新定义一个s2来使用。
struct S
{
char c;
int a;
short s;
}s;
int main()
{
struct S s2 = { 'a', 2, 1 };
printf("%c %d %d", s2.c, s2.a, s2.s);
return 0;
}
介绍一下匿名结构体类型,匿名结构体类型就是省略结构体的名字,因为没有名字,所以只能在定义的时候使用一次
struct//这里没有名字
{
char c;
int a;
short s;
}s;//只能在这里用一次
struct
{
char c;
int a;
short s;
}* ps;//在定义结构体时,就算俩结构体成员一样,也是单独的结构体
//所以,不能定义*ps操作s,编译器会提示类型不兼容
int main()
{
ps = &s;//类型不算相同的类型,即使这俩的元素相同
return 0;
}
结构体实现结点,也是结构体的自引用:
struct Node
{
int data;//数据域
struct Node* next;//指针域
};
结构体的嵌套初始化:
struct S
{
int a;
int b;
double d;
};
struct B
{
char c;
struct S s;
short ss;
};
int main()
{
struct B b = { 'a', { 1 , 1, 1.1 }, 1 };
printf("%lf\n", b.s.d);
return 0;
}
结构体内存对齐
结构体内存对齐是什么:结构体在计算大小的时候会发生对齐
为什么要有结构体内存对齐:结构体的内存对齐是拿空间来换取时间的做法。可以提高程序的效率。数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。同样结构体内存对齐也能增加程序的可移植性
结构体内存对齐的规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数与该成员大小的较小值。
VS中默认的值为8,Linux中的默认值为4 - 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
下面看几个结构体内存对齐的计算
`
#include<stdio.h>
struct S1
{
char c1;//占用0-1
int a;//1-2,2-3浪费,占用4-7
char c2;//占用8-9,9-10,,10-11,11-12浪费
};//输出12
struct S2
{
char c1;//占用0-1
char c2;//占用1-2,/2-3,3-4浪费
int i;//占用4-7,总计占用0-7,8个字节
};
struct S3
{
double d;//0-7
char c;//7-8
char i;//8-9,/10-11,11-12,12-15浪费,总计十六个
};
struct S4
{
char c1;//0-1
struct S3 s3;//如果嵌套了结构体的情况,
//嵌套的结构体对齐到自己的最大对齐数的整数倍处,
//结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
//这里对齐数为8,所以从8字节开始到23字节
double d;//24-31
};
int main()
{
printf("%d\n", sizeof(struct S1));
printf("%d\n", sizeof(struct S2));
printf("%d\n", sizeof(struct S3));
printf("%d\n", sizeof(struct S4));
return 0;
}//结构体内存对齐是拿空间换时间,得到效率上的提升
输出的结果:
12
8
16
32
请按任意键继续. .
注意:
使用结构体传参
最好是传地址,因为如果结构体较大,传值会有较大时间和空间上的系统开销,造成性能的下降