今天看面试宝典时遇到一个问题如下:
class A{
public:
double d;
float a;
int b;
char c;
A();
~A();
};
int mian()
{
cout<<sizeof(A);
}
以我对数据对齐的理解,d为8个字节,那么a,b,c均占8个字节,但是实际上是24个字节(在vc中测试的结果)。后来我打印出它的地址发现,&A.d=0x0012ff58,&A.a=0x0012ff60,&A.b=0x0012ff64,&A.c=0x0012ff68;
由此知道,d占八个字节,而float和int各占四个字节,但是依据数据对齐原理:对于n字节的元素(n=2,4,8,。。。),它的首地址能被n整除才能获得最好的性能。所以c只需一个字节即可,但是实际上编译器为A.c申请了8个字节。测试如下:
int main()
{
int test1;
A testA;
int test2;
printf("%08x %08x %08x %08x %08x %08x\n",&test2,&AA.d,&AA.a,&AA.b,&AA.c,&test1);
}
执行的结果为:0x0012ff54 0x0012ff58 0x0012ff60 0x0012ff64 0x0012ff68 0x0012ff70
由于test1、testA、test2等都是局部变量,均在栈中分配,且test1的地址高,而testA的地址较低,以此类推
从结果可以看出,testA的起始地址是0x0012ff58,结束地址为0x0012ff70,说明结构体A中的c分配了8个字节的空间。
结论:在编译器为变量分配内存时,会依据类型大小最大的变量来对齐(如double),如果有比着小的数据类型并且可以遵循数据对齐原理(上面所述)就是说下一个变量的开始地址必须是它本身的n倍才行,可以按找它自己的大小来分配(如int、float加起来真好是8个字节和double对齐),最后虽然c只是占用一个字节,但是在此结构体中需要和double对齐,所以也占据8个字节的空间,如果在c的后面加上多个char类型的变量(别超过7个),整个结构体的大小不会变,还是24,或者加入一个int型的变量,整个结构体的大小还是24。有了这些知识后看下面一个例题:
class B{
public:
bool m_bTemp;
int m_nTmep;
bool m_bTemp2;
};
class C{
public:
int m_nTmep;
bool m_bTemp;
bool m_bTmep2;
}
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
执行结果为:
12
8
在内存中的布局为:
类B:
| bool l ------ | ------ | ------ |
| --------------int-------------- |
| bool | bool | ------ | ------ |
类C:
| --------------int-------------- |
| bool | bool | ------ | ------ |
另外需要注意的是:char *str=“dafddsfasdfasdf”;
char str2[]="dfadfasdfasdf";
sizeof(str)=4;//仅仅是一个指针大小
sizeof(str2)=14;//包含\0的字符串大小