了解什么是结构体

1. 结构体类型的声明

结构体是一些值的集合,这些被统称为成员变量,结构的每一个成员类型是可以不同类型的变量。

可以是标量,数组,指针甚至是其他结构体

描述一个学生
struct stu
{
    char name[20];名字
    int age;年龄
    int sex[5];性别
    char id[20];学号
};

1.1 结构体的初始化

按结构体的成员顺序初始化
struct stu s = {"张三", 18, "男", A1234567};

按指定结构体的成员初始化
struct stu s = {.name = "张三", .age = 20, .id = A1234567, .sex = "男"};

1.2 结构体成员访问操作符

结构体可以通过( . ),和 -> 俩个操作来访问

想要打印结构体指定成员,就可以直接用 .  操作符

struct stu
{
    char name[20];名字
    int age;年龄
    int sex[5];性别
    char id[20];学号
};

struct stu s = {"张三", 18, "男", A1234567};
printf("%s\n", s.name);
这样就可以直接打印出名字

要时有些时候我们直接接受的不是一个结构体,而是一个结构体指针那我们就需要用 -> 操作符来直接访问结构体的成员

struct stu
{
    char name[20];名字
    int age;年龄
    int sex[5];性别
    char id[20];学号
};

struct stu s = {"张三", 18, "男", A1234567};
struct stu *p = s;
printf("%s\n", p -> name);

当然结构体指针也是可以通过 . 操作符来访问成员的,只不过需要先解引用再用 . 操作符来访问

只不过这样有点多此一举了,因为 -> 操作符就是专门用来访问结构体指针成员的

1.3 结构的特殊声明

在声明结构的时候,可以不完全声明。

struct 
{
    char name[20];
    int age;
}x;

这种被称为匿名结构体类型,这种类型如果没有对结构体重命名的话,基本只能使用一次。

1.4 结构体的自引用

结构体包含一个结构体本身是无穷大的,是不合理的,正确应该包含同类的指针。

struct st
{
    int n;
    sttuct st* next;
};

2. 结构体内存对齐

2.1 对齐规则

1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处

2. 其他成员变量要对齐到对齐数的整数倍的地址处。

  • 对齐数是编译器默认的一个对齐数与该成员变量大小的较小值。
  • VS中默认的值是8

3. 结构体总大小为最大对齐数的整数倍

4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己成员中最大对齐数的整数倍处,结构体大小就是所以最大对齐数的整数

俩个结构体里面的成员数量类型完全一样,只是存放顺序不一样,那他们大小是一样的吗
struct st st1
{
    int a ;
    char b;
    char c;
};
struct st st2
{
    char b;
    int a;
    char c;
}
printf("st1 = %zd", st1);
printf("st2 = %zd", st2);

运行程序

str1 = 8
str2 = 12;
struct st st1 在VS中默认值是8,对齐数是编译器和成员变量大小比较而取的较小值
{
    int a ;    int 大小为 4 ,VS 为8, 默认从偏移量为 0 的地址开始存储,存储4个字节大小
    char b;    char 大小为 1 ,对齐数是 1 要从对齐数的整数倍开始存储,从 5 开始存, 
                                                                5 是 1 的整数倍存进去了
    char c;  紧接着存 1 从 6 开始存刚好也是整数倍。
}; 结构体总大小为最大对齐数的整数倍, st1 最大对齐数是 4 结构体大小要取 
4 的整数倍我们已经存了6个字节但是 6 不是 4 的整数倍,
那我们往大拿取个 8 ,8是4的俩倍。所以st1结构体大小为8个字节
    
struct st st2 
{
    char b; 一样从偏移量为 0 开始存 存了 1个字节, 
    int a;    这个要存 4 个字节但是 2 不是4 的整数倍,只能从 4 开始存 4 个字节
    char c; 存为上个数后大小已经为 8 了 这里存 一个字节 为 9
};结构体总大小为最大对齐数的整数倍,st2 最大对齐数是 4,9 不是 4的整数倍,往上取 16 ,
所以 st2 大小为16

同样结构体包含一个结构体变量也是按照顺序来一个个存储

struct st1
{
	int a; 4
	char b; 1
};
struct st2
{
	char a;  1
	struct st s; 4
};
st2 先会存 1 然后开始存 st1 ,st1最大对齐数是 4 从 4 开始存,
存入一个int, st2现在大小为 8 了开始存char 大小为 9 。
结构体总大小为最大对齐数的整数倍
取最大对齐数的整数倍,包含在st2的str1 最大对齐数是 4 而。
st2 其他成员的对齐数最大只为1 ,所以str2最大对齐数取 4 现在大小为9 
不是4的整数倍,取12,所以st2结构体大小为12.  

2.2 为什么存在内存对齐

结构体的内存对齐是拿空间来换取时间的

我们在设计结构体的时候,要节省空间的话尽量让占用空间小的成员方一起。

#pragme 这个预处理指令,可以改变编译器的默认对齐数1

#pragma park(1)//设置默认对齐数为1

结构体在对齐方式不合适的时候,我们可以用这个更改默认对齐数。

3. 结构体传参

struct st st1
{
    char name[10];
    int age; 
};
void pfst(struct st* p)
{
    printf("%d\n", p -> age);
}
int main()
{
    struct st st1 = {"LILI", 18};
    pfst(&st1)
    return 0;

函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。

如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

结构体传参的时候,要传结构体的地址。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值