平台为32位的kali以及windows11 64位
编译器为gcc (Debian ) 以及 mingw gcc
(资料图片)
注意:1,本文补零只是一个说法,大致意思就是填充,至于填充什么,我暂时以零算,所以叫补零
2,本文只是我个人探究得出结论,总体基本上都是在平台上测试过,如有不对的地方,还望大家指正,在这里叩谢了。
本文最佳阅读我个人觉得,可用先‘简单’阅读一下内容直到介绍4位与8位补齐,认真看一下位对齐策略4位8位补齐以及极限算法,然后再回过头重新看一遍,基本上就完事了。
下面开始!
核心:探究得出位域规律核心内容如下
整体趋向于最大的位数对齐(结构中位最大的类型)确定结构的对齐字节
“位域无法跨越字节” 当前类型位域能放下的放在一起 不能放下的 剩余字节位域补零 补零后在下一字节开始 存入下一成员 已存放类型位置不变
两参数临近存放 如果位域超过了前一个成员类型位域大小 先填入前面参数 字节的剩余位域补零 下一字节存放第二个成员
到这里,没事,不要紧,你看不明白很正常,我总结的都费劲嫌自己啰嗦,更别说你只是看了,接下来才是重点,上面只是留个映像。
”重要!!!“总之记住下面这三点 括号内的看一眼有点映像就好了
1, 先找出位域最大的类型 这个结构体自能是该类型的倍数大小(包括一倍)
2,搞清楚位和字节的区别 当前平台下1字节等于8位 有8位补齐策略(还有4位补齐和极限算法,8位补齐意思就是不足八个,将8位中剩余几个补零,需要存的数据必须再八位以后存放 4位补齐就是不足4位的 把4位剩余几个补零,需要存的数据可再4位后存放)
3,“从前向后” 类型相同能挤就挤
下面是例子:
1,能挤就挤
struct{
char a:3;
char b:4;
} 3+4<8 能挤下 就占一个字节,也就是8位
2,不能挤就当前类型字节补零 重开字节存储
struct{
char a:3;
char b:6;
} 3+6>8 不能挤 第一个参数存入 剩余字节位域补零 在当前类型下一个字节存放
3,不相同就按最大的 但类型最大位域还是要遵守
struct{
char a:3;
short b:4;
} 3+4<8 能挤下 就占一个字节 但结构必须是最大位域类型的倍数 不足的需要补零 所以当前就占两个字节(short是2个字节)除了放置数据的 其他位置全补零
4,不能挤下还有类型差
struct{
char a:3;
short b:6;
} 3+6>8 不能挤 第一个参数存入 剩余字节位域补零 在当前类型下一个字节存放 存放完补零 补完再补整体最大类型位域的空位 当前结构最大类型是short 就等于两个数据加起来位域必须得是short的位域倍数 不足的补零 a占一个字节 b占一个字节 刚好满足short位域倍数(1倍:16位)
5,不能挤
struct{
char a:3;
short b:12;
} 3+12>8 不能挤 第一个参数存入 剩余字节位域补零 在当前类型下一个字节存放 但b有12位 一个字节存不下 所以就提升到当前类型字节(char->short 8位变成16位) 存放完补零 补完再补整体最大类型位域的空位 当前结构最大类型是int 就等于两个数据加起来位域必须得是int的位域倍数 不足的补零 a占一个字节 b占一个字节 刚好满足short位域倍数(1倍:16位)
6,不能挤
struct{
char a:3;
short b:14;
} 3+14>8 不能挤 第一个参数存入 剩余字节位域补零 在当前类型下一个字节存放 但b有14位 一个字节存不下 所以就提升到当前类型字节(char->short 8位变成16位) 存放完补零 补完再补整体最大类型位域的空位 当前结构最大类型是short 就等于两个数据加起来位域必须得是short的位域倍数 不足的补零 a占一个字节 b占2个字节 整体补零一个字节 刚好满足2个short位域倍数(2倍:32位)
7,不能挤
struct{
char a:3;
int b:30;
} 再介绍一下这种情况 明显ab位域char的位域满足不了 所以a补齐8位 然后填入b的内容 b再补齐自己类型位域 最后执行整体位域补齐,当前整体位域开篇就说过,这里是int的倍数 而当前一个int位域肯定放不下 所以就两个 多的空域补零
8,不能挤
struct{
char a:3;
int b:30;
char c:3;
} 这个结构再我的环境下占12字节 为什么? 因为前面两个的两个int位根据开篇说的从前向后规则已经是定了的,而且b和c凑一起是大于int位域位数 所以挤不了 只能再开一片空间存储 这时候结构要执行整体位域补齐 所以c后面将整体补零满足要求 大致就是c占3位 填补5位 b占30位 填补2位 填补24位 c占3位 填补5位 填补24位 整体填补0位 最终占96位 12字节
9,后面可用挤
struct{
char a:3;
int b:30;
char c:2;
} 这种你以为还是和上面一样吗 不 这个的b和c刚好能执行极限算法 下面有介绍极限算法 a占3位 补5位 b占30位 c占2位 补0位 整体补24位 最终占64位 8字节
小重点啦!!!位对齐策略解释一下4位补齐与8位补齐策略区别
struct{
char a:3;
short b:6;
}
8位中 a+b>8 不能一起存放 a后面的位域要补零 补足8位 二进制也就是a**00000 b******00
4位中 a+b>8 不能一起存放 a后面的位域要补零 补足4位 二进制也就是a**0 b** ***0000000
问有什么作用?来看
struct{
char a:3;
short b:12;
}
8位中 a+b>8 不能一起存放 a后面的位域要补零 补足8位 也就是a**00000 b******* ****0000 00000000 最终4字节 说明一下 这是两个short 不是提升到int了 开篇就说过 ,只能是最大类型的倍数 这种情况就是两个short位域大小 其中第21到24是short补齐 25到32 是整体补齐,满足最大类型倍数的要求
4位中 a+b>8 不能一起存放 a后面的位域要补零 补足4位 也就是a**0b*** ********最终2字节
大重点!!!最后再说一下一种极限算法 如今很多都是以这种为主 4位8位补齐是备选
struct{
char a:3;
short b:13;
}
极限算法:a**b**** ******** 只要填不满 我就不添加类型位域空间 最终2字节
struct{
char a:3;
short b:14;
}
这种情况极限算法也没招 就看第二支持的是8位还是4位对齐了
8位a**00000 b******* ******00 00000000
4位a**0b*** ******** **000000 00000000
现在你明白了吗?
还不明白 去看一下开篇的中心内容 三点要记下的东西 再看一下位对齐策略 最后去看一下例子
再不明白,集齐万赞或千币我出视频好吧。
辛苦了您,感谢阅读。
关键词: