当前位置: 首页> 健康> 知识 > 结构体的声明和内存对齐

结构体的声明和内存对齐

时间:2025/7/10 10:25:05来源:https://blog.csdn.net/m0_75007575/article/details/141367924 浏览次数:0次

结构体

声明

struct Student
{
    char name; //姓名
    int age;       //年龄
    char sex[5];//性别
};                    //分号不能丢

初始化

定义结构体变量p,并且初始化

Student p={"博雅",19,"女"};

指定顺序初始化

Student s={.age=15,.name="张三"};

结构体的特殊声明

但是匿名结构体类型只能用一次,在声明时省略了标签(tag)
 

结构体自引用

可以包含一个同类型的结构体指针

typedef类型重命名,将struct node——node

也可以这样写

但是匿名的结构体类型不能实现结构体自引用是效果

结构体内存对齐

计算结构体的大小

对齐规则

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
  2. 其它成员要对齐到某个数字(对齐数)的整数倍地址

对齐数=编译器默认的对齐数 与 该成员变量大小的较小值(VS默认的值为8,Linux中gcc没有对齐数,对齐数就是成员自身的大小)

  1. 结构体的总大小是最大对齐数(结构体每一个成员都有一个对齐数)的整数倍
  2. 如果嵌套了结构体情况,嵌套的结构体成员对齐到自己成员中最大对齐数的整数倍,结构体的整体大小就是所有最大对齐数的整数倍

练习一

struct S1
{char c1;int i;char c2;
};
printf("%d\n", sizeof(struct S1));//12

所以i要对齐到4的倍数的地址处,也就是4,所以i从4开始存起。

c2的大小是1个字节,VS默认是8,他两的较小值是8,所以对齐数数1,所以c2只占一个字节,所以加起来为9

c1的对齐数是1,i的对齐数是4,c2的对齐数是1,所以最大对齐数是4,

而9不是4的倍数,所以我们结构体总大小是12(4×3=12)

练习二

struct S2
{char c1;//1 8——1char c2;//1 8——1int i;  //4 8——4
};
printf("%d\n", sizeof(struct S2));

c1占1个字节,c2也是1,但是i的偏移量要是4的整数倍,所以必须是4开始,1+3+4=8个字节

练习三

struct S3
{double d;//8 8——8char c;//1 8 ——1int i;// 4 8——4
};
printf("%d\n", sizeof(struct S3));

i从4的整数倍的地址开始,所以是从12开始往下4个字节。15不是8的整数倍,所以16是结构体的总大小

练习四:结构体嵌套问题

struct S3
{double d;//8 8——8char c;//1 8 ——1int i;// 4 8——4
};
struct S4
{char c1;//1 8——1struct S3 s3;//成员中最大对齐数是8,从8的倍数开始,s3大小是16个字节  double d;//8 8——8
};
printf("%d\n", sizeof(struct S4));

因为所有最大对齐数是8,所以内存是8的倍数,32是8的倍数,所以结构体大小是32

如果结构体中有数组怎么办?

char c1[5]按照5个char存即可,也就是5个字节

int c1[5]按照5个int存即可,就是4×5=20个字节

为什么要内存对齐

提升时间,拿空间换时间的做法

修改对齐数

#pragama可以改变编译器的默认对齐数

直接访问

也可以传递地址,间接访问

结论:结构体传参的时候,尽量传结构体的地址

结构体实现位段

位段(二进制位)的声明和结构是类似的,有两个不同

专业用来节省内存的,加上数字后,规定了a占2个bit位,b占5个bit位,c占10个bit位

  1. 位段的成员必须是
  2. 位段的成员名后面有一个:和数字

结构体 位段

%zd打印无符号整数

位段的内存分配

  1. 位段成员可以是int、unsigned int、signed int或者是char等类型
  2. 尾端的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应避免使用位段
  4. 申请到的一块内存中,从左向右使用,还是从右向左使用,是不确定的,VS编译器里面是从右向左使用
  5. 剩余的空间不组织下一个成员使用的时候,是浪费还是使用呢?在VS中是浪费

首先申请1个字节(char),a占3个bit,b占4个bit,c要占5个bit但是空间不够,直接浪费,再往后申请1个字节

所以可知s占3个字节

转换成16进制

a中存10:0001010

b中存12:0001100

c中存3: 0000011

d中存4: 0000100

位段的跨平台问题

  1. int位段被当成有符号还是无符号数是不确定的
  2. 位段中最大的树木不能确定
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义

位段

不能对位段式结构的成员直接取地址

只能先放在一个变量中,然后再赋值给位段成员

关键字:结构体的声明和内存对齐

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: