本文尽量全面覆盖计算结构体/类的大小计算的所以知识点,故每一部分不会写的很详细,若有不准确的地方可以在评论去讨论。
计算结构体大小时比较难且失误率比较高的面试题,实际变成中,个人感觉用处不大。
字节对齐的好处是提供CPU读效率,防止一次读对应多次汇编指令。在编写有关数据帧时,可使用“#pragma pack(1)”来取消字节对齐。数据帧要提供读效率的话,应从数据帧协议出直接考虑,而不是让结构体自动帮我们添加,这样容易出错。
目录
1 C语言中结构体大小(字节对其原则)
前提:熟悉在不同系统下基本类型的大小。[1][2]
第一步:default setting : platform_alignment_size == (systemBits / 8) or "#pragma pack(x)" setting
第二步:max_elemVar_size = min(max_elemVar_size, platform_alignment_size )
1、class_pos_begin % Xmax_elemVar_size == 0
2、 class_size % Xmax_elemVar_size == 0
3、 if elemVar is nested class, then ,elem_size = max_elemVar_size in nested class.
Xelem_size = min(elem_size, platform_alignment_size) , pos_elem % Xelem_size == 0
注:elemVar为成员变量,X前缀表示修正量,pos表示位置,
确定平台的简单方法:平台简单说是由CPU、OS 和Compiler组成的,要使用64位的平台,那么CPU应该是支持64位的,OS应选择64位的,Compiler也应选择64位的,缺一不可。
4、特例:空结构体的大小为1字节。
2 测试程序1
2.1 平台测试程序:
#include <iostream>
#pragma pack()
int main()
{
cout << "sizeof(void*):" << sizeof(void*) << endl;
cout << "sizeof(char):" << sizeof(char) << endl;
cout << "sizeof(short):" << sizeof(short) << endl;
cout << "sizeof(int):" << sizeof(int) << endl;
cout << "sizeof(long):" << sizeof(long) << endl;
cout << "sizeof(long long):" << sizeof(long long) << endl;
return 0;
}
2.2 结构体大小理解测试程序:[3]
#include <iostream>
// 字节对齐长度->程序输出结果:1->13 2->14 4->16 8->24
#pragma pack(4)
using namespace std;
struct S2_t
{
int a ;
double c ;
char b ;
};
#pragma pack()
int main()
{
cout<<sizeof(S2_t)<<endl;
return 0;
}
//attention: struct S3_t{cha a,b,c};, sizeof(S3_t) always 3
2.3 结构体套结构体测试:[4]
#pragma pack(8):
struct TestStruct4
{
char a;
long b;//假设是4字节的long
};
struct TestStruct5
{
char c;
struct TestStruct4 d;
long long e;
};
siseof(struct TestStruct5)==24
所在字节位置为:1xxx 1xxx 1111 xxxx 11111111
3 C++类对象的大小
在C语言结构体大小理解的基础上,还需要考虑:[6]
- 类的大小与普通数据成员有关,与成员函数和静态成员无关。即普通成员函数,静态成员函数,静态数据成员,静态常量数据成员均对类的大小无影响。[5]
- 虚函数对类的大小有影响,是因为虚函数表指针带来的影响。
- 虚继承对类的大小有影响,是因为虚基表指针带来的影响。
- 空类的大小是一个特殊情况,空类的大小为1。
1、继承时:当派生类继承空类后,派生类如果有自己的数据成员,而空基类的一个字节并不会加到派生类中去;
2、作为嵌套的成员变量:看做1个字节的成员函数;
3、各嵌套的类都为空:总大小为1个字节。
计算C++对象的大小过程中,最重要的就是需要知道哪些成员变量在前,哪些成员变量在后。这个问题再存在继承和虚函数是将变得比较复杂。
4 测试程序2
注:以下测试实在vs32下进行的,
4.1 继承顺序问题
#include<iostream>
using namespace std;
#pragma pack(8)
class A
{
char a=1;
};
class B
{
double b=2;
};
class C :public A, public B
{
int c=3;
};
int main(void)
{
C cc;
cout << sizeof(void*) << endl;
cout << sizeof(cc)<<endl;
return 0;
}
故占用大小为24个字节。
4.2 虚函数表的位置
5 参考资料
注:参考资料的准确性请自行判断,笔者不做评价。
[3]C语言中结构体对齐问题
[4]关于内存对齐
[6]c++类的大小计算