C++⾯试题之sizeof⾯试题//sizeof⾯试题1.cpp
//What is the output of the following code?
//[美国某著名计算机软硬件公司⾯试题]
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct{
short a1;
short a2;
short a3;
}A;
struct{
long a1;
short a2;
}B;
int main()
{
char* ss1="0123456789";
char ss2[]="0123456789";
char ss3[100]="0123456789";
int ss4[100];
char q1[]="abc";
char q2[]="a/n";
char* q3="a/n";
char* str1=(char*)malloc(100);
void *str2=(void*)malloc(100);
cout<<sizeof(ss1)<<" ";
cout<<sizeof(ss2)<<" ";
cout<<sizeof(ss3)<<" ";
cout<<sizeof(ss4)<<" ";
cout<<sizeof(q1)<<" ";
cout<<sizeof(q2)<<" ";
cout<<sizeof(q3)<<" ";
cout<<sizeof(A)<<" ";
cout<<sizeof(B)<<" ";sizeof 指针
cout<<sizeof(str1)<<" ";
cout<<sizeof(str2)<<" ";
return 0;
}
//解析:
//ss1是⼀个字符指针,指针的⼤⼩是⼀个定植,就是4。
//q2⾥⾯有⼀个"/n","/n"算做⼀位,所以它的空间⼤⼩是3。
//A 和B是两个结构体。在默认情况下,为了⽅便对结构体内元素的访问和管理,当结构体内的元素的长度都
//⼩于处理器的位数的时候,便以结构体⾥⾯最长的数据元素为对齐单位,也就是说,结构体的长度⼀定是
//最长的数据元素的整数倍。如果结构体内存在长度⼤于处理器位数的元素,那么就以处理器的位数为对齐
//单位。但是结构体内类型相同的连续元素将在连续的空间内,和数组⼀样。
//
//结构体A中有3个short类型变量,各⾃以2字节对齐,结构体对齐参数按默认的8字节对齐,则a1、a2、a3都
//取2字节对齐,sizeof(A)为6,其也是2的整数倍。B中a1为4字节对齐,a2 为2字节对齐,结构体默认对齐参数//为8,则a1取2字节对齐;结构体⼤⼩6字节,6不为4的整数倍,增加到8时,符合所有条件,则sizeof(B)为8。//
//CPU的优化规则⼤致原则是这样的:对于n字节的元素(n=2,4,8,...) ,它的⾸地址能被n整除,才能获得最好的//性能。设计编译器的时候可以遵循这个原则:对于每⼀个变量,可以从当前位置向后到第⼀个满⾜这个条件
//的地址作为⾸地址。例⼦⽐较特殊,因为即使采⽤这个原则,得到的结果也应该为6(long的⾸地址偏移量0000 //,short⾸地址偏移量0004,都符合要求)。但是结构体⼀般会⾯临数组分配的问题。编译器为了优化这种情况,//⼲脆把它的⼤⼩设为8,这样就没有⿇烦了,否则的话,会出现单个结构体的⼤⼩为6,⽽⼤⼩为n的结构体
//数组⼤⼩却为8*(n-1)+6的尴尬局⾯。IBM出这道题并不在于考查理解语⾔本⾝和编译器,⽽在于应聘者对
//计算机底层机制的理解和设计程序的原则。也就是说,如果让你设计编译器,你将怎样解决内存对齐的问题。
//sizeof⾯试题2.cpp
//What is the ouput of the following code?
//[德国某著名电⼦/通信/IT企业2005年11⽉⾯试题]
#include<iostream>
using namespace std;
class A{
};
class A2{
char d,e;
};
struct B{
};
struct C{
char b,c;
};
struct D{
int x,y;
};
{
cout<<sizeof(A)<<endl;
cout<<sizeof(A2)<<endl;
A *p1=new A();
A p2;
A *p3;
cout<<sizeof(p1)<<endl;
cout<<sizeof(p2)<<endl;
cout<<sizeof(p3)<<endl;
cout<<sizeof(B)<<endl;
cout<<sizeof(C)<<endl;
cout<<sizeof(D)<<endl;
return 0;
}
//解析:
// 对于⼀个类⽽⾔,即使它是⼀个空的类,编译器仍然要给它⼀个空间,所以类A即便什么都没有,它的空间⼤⼩//依然是1。
//sizeof⾯试题3.cpp
//求解下⾯程序的结果。
//[中国某著名通信企业H⾯试题]
#include<iostream>
using namespace std;
class A1{
public:
int a;
static int b;
A1();
~A1();
};
class A2{
public:
int a;
char c;
A2();
~A2();
};
class A3{
public:
float a;
char c;
A3();
~A3();
};
public:
float a;
int b;
char c;
A4();
~A4();
};
class A5{
public:
double d;
float a;
int b;
char c,e;
A5();
~A5();
};
int main()
{
cout<<sizeof(A1)<<endl;
cout<<sizeof(A2)<<endl;
cout<<sizeof(A3)<<endl;
cout<<sizeof(A4)<<endl;
cout<<sizeof(A5)<<endl;
return 0;
}
//解析:
//因为静态变量是存放在全局数据区的,⽽sizeof计算栈中分配的⼤⼩,是不会计算在内的,所以sizeof(A1) //是4。
//为了照顾数据对齐,int⼤⼩为4,char⼤⼩为1,所以sizeof(A2)是8。
// 为了照顾数据对齐,float⼤⼩为4,char⼤⼩为1,所以sizeof(A3)是8。
// 为了照顾数据对齐,float⼤⼩为4,int⼤⼩为4,char⼤⼩为1,所以sizeof(A4)是12。
// 为了照顾数据对齐,double⼤⼩是8,float⼤⼩为4,int⼤⼩为4,char⼤⼩为1,所以sizeof(A5)是24。
//数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍。DWORD数据的内存起始地址能被
4除尽,
//WORD数据的内存起始地址能被2除尽。x86 CPU能直接访问对齐的数据,当它试图访问⼀个未对齐的数据时,//会在内部进⾏⼀系列的调整。
//这些调整对于程序来说是透明的,但是会降低运⾏速度,所以编译器在编译程序时会尽量保证数据对齐。
//同样⼀段代码,我们来看看⽤VC、Dev C++和LCC这3个不同的编译器编译出来的程序的执⾏结果:
//#include<stdio.h>
//int mainc()
//{
// int a;
// char b;
// int c;
// printf("0x%08x",&a);
// printf("0x%08x",&b);
// printf("0x%08x",&c);
// return 0;
//}
//这是⽤VC编译后的执⾏结果:
// 0x0012ff7c
// 0x0012ff7b
// 0x0012ff80
//变量在内存中的顺序:b(1字节)--a(4字节)--c(4字节)。
//这是⽤Dev C++编译后的执⾏结果:
/
/ 0x0022ff7c
// 0x0022ff7b
// 0x0012ff74
//变量在内存中的顺序:c(4字节)--中间相隔3字节--b(占1字节)--a(4字节)。
//这是⽤LCC编译后的执⾏结果:
// 0x0012ff6c
// 0x0012ff6b
// 0x0012ff64
//变量在内存中的顺序:同上。
//三个编译器都做到了数据对齐,但是后两个编译器显然没VC“聪明”,让⼀个char占了4字节,浪费内存。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。