博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
计算结构体大小
阅读量:3949 次
发布时间:2019-05-24

本文共 1497 字,大约阅读时间需要 4 分钟。

原本以为结构体的大小就是里边各个成员变量的大小总和,但是运行结构并不是这样,原来结构体大小计算还有一个规则——内存对齐

  • 内存对齐规则

1.第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
从零偏移处开始,按字节大小计算,判断此偏移地址是否为该成员变量和对齐参数两者之间的最小值,若是,则从此处开始占用内存,大小为该类型所占字节数值,若不是,则内存向后偏移到最小值整数倍处,再开始占用空间。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所最大对齐数(含嵌套结构体的对齐数)的整数倍。

  • VS中默认的值为8,Linux中的默认值为4

举个栗子:

struct S1{
char c1; int i; char c2;};

这里就不加运行结果的图片了,结果是 12 。因为我用的是 VS,所以默认对齐数为 4,第一个 c1 的大小是1,所以对齐数为 1,第二个 i 的大小为 4,所以对齐数是 4,与前边的 c1 对齐,则 c1 要再向后偏移 3 个字节,成为 4 个字节才能对齐,最后一个 c2 的大小是 1 ,对齐数也就是 1 ,加在一起就是 4+4+1 = 9,因为还有一个规则是结构体总大小要是最大对齐数的整数倍,现在的最大对齐数是 4 ,要是 4 的整数倍,则需要再补上 3 个字节总大小就是 12 个字节,也就是最大对齐数(4)的整数倍了。

再举个栗子

struct S2{
char c1; char c2; int i;};

这个结果是 8,因为 c1 和 c2 的对齐数为1,对齐玩=完之后偏移量为 2 ,2 不是 4 的整数倍,所以再往后偏移两位,偏移量为 4 的时候,可以与 i 对齐,与 i 对齐之后,偏移量为 8,也是最大对齐数(4)的整数倍,所以最后结果为 8。

看一个结构体对齐的

struct S1{
double d; char c; int i;};struct S2 {
char c1; struct S1 s1; double d;};int main() {
printf("%d\n", sizeof(struct S1)); printf("%d\n", sizeof(struct S2)); return 0;}

在这里插入图片描述

首先,S1 的大小是 16,d 的大小是 8 ,d 对齐后偏移量为 8,是 1 的倍数,所以 c 对齐后是偏移量是 9 ,9 不是 4 的倍数,偏移到 12是 4 的倍数,再加上 i 结果就是 16 个字节。
S2 的大小,首先 c1 大小是 1,偏移量也即是 1 ,然后对齐结构体 S1,结构体要对齐它的最大对齐数的整数倍(即结构体的大小16),对齐之后偏移量为 18,不是后边 d 的整数倍,直到偏移量为 24 ,d 可以对齐,对齐之后结果为 32 。

当然,默认对齐数是可以改变的。#pragma pack(n) 这个指令就可以改变默认对齐数,n 是要改变的值。

为什么结构体要对齐?

这是一种以空间换时间的做法,数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器
需要作两次内存访问;而对齐的内存访问仅需要一次访问

修改默认对齐数

使用 #pragma pack(n)
n 是多少 就是设置对齐数为多少

转载地址:http://eqwzi.baihongyu.com/

你可能感兴趣的文章
jvm为什么把-Xms和-Xmx的值设置成一样
查看>>
2021-01-21对map进行key或者value排序
查看>>
ConcurrentHashMap 1.7和1.8的区别
查看>>
阻塞锁与自旋锁
查看>>
【面试官:select语句和update语句分别是怎么执行的
查看>>
scala学习之安装问题
查看>>
LDAP常见错误码
查看>>
linux yum安装rpm包出现问题
查看>>
idea编译报错类似xxx.java:[85,65] 错误: 找不到符号
查看>>
ArrayList复制
查看>>
idea打开项目时,文件左下角显示橙色J
查看>>
SQL注入
查看>>
linux中ldconfig的使用介绍
查看>>
ldap适合入门学习
查看>>
ldap学习参考博客
查看>>
linux学习之source命令与alias(别名)使用
查看>>
MYSQL常用查询
查看>>
安装Linux虚拟机绑定IP操作
查看>>
centos7离线安装 mysql
查看>>
mysql学习使用一(查询)
查看>>