打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
如何理解 C++ 中这两个结构体的大小(size)?
  • 这个例子输出的结果是 3。按照字节对齐的情况来说结果不应该是等同于 #pragma pack(show) 的数值吗,然而 #pragma pack(n) 中,不管 n 设置多少结果都为 3。

struct Test {
char a[3];
};

int main(){
cout << sizeof(Test) << endl;
return 0;
}
  • 这个例子输出的结果是 6。按照字节对齐的情况来说结果不应该是 8 吗,就算按照上个例子 char 数组在结构体中的特殊性来看,结果也应该是 5 而不应该是 6。

struct Test {
short a;
char b[3];
};

int main(){
cout << sizeof(Test) << endl;
return 0;
}

这个和结构体对齐规则有关,现在已经成显学了,到网上搜一下到处都是。

比如:字节对齐,看这篇就懂了 - 云+社区 - 腾讯云

因此,对第一个结构体,a的首地址是0,无需对齐;又因为只有它一个元素,因此自然是数据多长结构体就多大(也就是3)。

而对第二个结构体,里面最长的数据是short,因此结构体最大小必须是sizeof(short)的整数倍。所以它的总大小是6。

进一步的,pack不为1时,结构体元素的排列顺序也可能影响它的最终大小。

比如,假设int大小为4,pack大于等于4;那么char int short顺序排列的结构体就会比char short int更大,你可以依照规则自己分析。


好吧,搜了下中文铺天盖地,但没几个能说清楚的;最后选了个腾讯的,没仔细看,觉得这个应该错不了了,大厂嘛。

结果还是错的,少一条:当pack值小于结构体里面最长的元素时,仍然以pack值为准;当pack值大于结构体里面最长的元素时,才可以用那三条标准(但写的啰里啰唆,没抓到根子)。

当然,正常来说,pack这个知识点最重要的是知道它的存在,没必要记住所有规则,因为随时能查资料。但没想到中文互联网的信息污染已经到了这个程度……

IBM Knowledge Center

这个文档有些老,它仍然认为pack(8)处于保留待将来使用状态;但稍微推导一下不难知道pack(8)的表现。

简单总结一下:

1、各种数据,当其开始地址等于自己长度的整数倍时,这就叫“自然对齐”。

但没有找到诸如char[3]这样的结构会否向上对齐到1、2、4、8的确切论述;在gcc 9.3.0上是会向上取整的。

此外,目标平台的CPU位宽小于pack/自然对齐约束时,也会忽略过高的对齐字节数,比如32位平台上搞64位对齐是无意义的(当然只要编译器支持,你完全可以声明和使用int64_t类型的数据)。

另外,如果某个CPU是奇葩的3字节总线位宽时如何处理也是空白。

总之里面模棱两可的东西很多;但C/C++是做工程的,这种状况是常态。我们只要明白常规情况下表现如何即可,不必过于纠结。

2、用pack(N)指定一个特定的N,这叫做强制对齐

3、任何一个数据(不管在不在结构体里面),其开始地址要么等于“自然对齐”的整数倍,要么等于“强制对齐”的整数倍,以两者间更小的那个为准

比如你规定了pack(1),那么所有数据无条件紧密排列;而规定了pack(2),那么int32就不再按4字节的整数倍设置开始地址,而是按2字节的整数倍设置地址。同样的,规定了pack(8),int32仍然会按4字节的整数倍设置开始地址,并不会按8字节的整数倍放置。

4、对于结构体,它的大小只能是“结构体里面自然对齐最大的那个元素的自然对齐值”和“强制对齐值”中、较小的那个的整数倍。

比如一个结构体里面最大的元素是一个int32,那么pack(2)时,其大小就向上取整到2的倍数;pack(8)时则向上取整到4的倍数。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
结构体(含位域)的sizeof
C语言结构体对齐问题
实例讲解C语言编程中的结构体对齐
C语言中的字节对齐
关于内存对齐
简要讲述C/C++中的操作符sizeof()
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服