结构体类型数据

1.结构体类型的声明

struct stu
{
    char name[20];//姓名
    int age;//年龄
};

例如,一个学生拥有姓名和年龄两种信息,就可以通过结构体类型对一个学生相关的两个变量进行描述。

创建完结构体变量后,就可以进行初始化:

#include <stdio.h>
struct stu
{
    char name[20];//姓名
    int age;//年龄
};

int main()
{
    //按顺序初始化
    struct stu s = {"张三", 18};
    //指定顺序初始化
    struct stu s1 = {.age = 21, .name = "李四"};
    return 0;
}

结构体在声明时,可以不对结构体类型进行重命名,例如省略上面代码中的stu,这样做的后果就是匿名的结构体类型只能用一次。

结构体可以做到自引用,但是不是直接把结构体变量包含进结构体内部,而是借助指针:

struct stu
{
    int age
    struct stu* next;
};

2.结构体内存对齐

结构体在内存中储存时有一定的规则:

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处;
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;//对齐数指编译器默认的对齐数 与 该成员变量大小的较小值
  3. 结构体总大小为最大对齐数(每一个成员都有对齐数,取所有对齐数中的最大值)的整数倍;
  4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍

只看以上文字有些云里雾里的,我们需要通过实战来感受结构体的内存对齐,例如:

struct s1
{
    double d;
    char c;
    int i;
};

 首先,d在内存偏移量为0的地方开始,由于d是double类型,因此d的对齐数为8个字节,同理c的对齐数为1个字节,i的对齐数为4个字节。那么c就应该在内存偏移量为8的地方,而i为了对齐到4的整数倍的地址处,应该在内存偏移量为12的地方,那么该结构体内存大小应该是16个字节。

接下来再来考虑一下嵌套的情况:

struct s2
{
    char c;
    struct s1 s;
    double d;
};

c的对齐数是1,s的对齐数则是s1中的最大对齐数也就是8,d的对齐数也是8。c在内存偏移量为0的地方,s为了对齐,在内存偏移量为8的地方,而由于s1的内存大小是16个字节,那么d在内存偏移量为24的地方,最后结构体s2的内存大小应该为32个字节。

为什么会有内存对齐呢,有平台方面的原因(方便代码移植),也有性能方面的原因(减少访问次数),总的来说,是一种用空间换时间的做法。

默认对齐数是可以修改的,前文由于作者使用的是vs,默认对齐数为8,double的对齐数就是8,而使用代码,例如:#pragma pack(1),就可以将默认对齐数修改为1,此时结构体就不存在内存对齐了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值