面试---sizeof

来源:互联网 发布:禁止修改ip软件 编辑:程序博客网 时间:2024/06/05 09:01

1、有一个如下的结构体:

struct A{ long a1; short a2; int a3; int *a4;};

请问在64位编译器下用sizeof(struct A)计算出的大小是多少?(24)

8 + 2 + 4 + 8 = 22, 对齐为8的倍数:2432位编译器:32位系统下指针占用4字节      char1个字节      char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)      short int : 2个字节      int4个字节      unsigned int : 4个字节      float:  4个字节      double:   8个字节      long:   4个字节      long long:  8个字节      unsigned long:  4个字节64位编译器:64位系统下指针占用8字节      char1个字节      char*(即指针变量): 8个字节      short int : 2个字节      int4个字节      unsigned int : 4个字节      float:  4个字节      double:   8个字节      long:   8个字节      long long:  8个字节      unsigned long:  8个字节

2、再看下例:32位编译器

#include <iostream>#include<string.h>#include<stdlib.h>using namespace std;/*结构体的内存空间:a. 当结构体内元素的长度都小于处理器的位数时:以结构体内最长的数据元素为对齐单位,即结构体的长度一定是最长数据元素的整数倍。b. 当结构体内存在长度大于处理器位数的元素时,以处理器的位数为对齐单位,但是结构体内类型相同的连续元素将在连续的空间内。*//*结构体A中3个short类型,各自以2字节对齐,结构体对齐参数按默认的8字节对齐则a1,a2,a3都取2字节对齐,sizeof(A)=6!!!!,也是2的整数倍。*/struct{    short a1;//2    short a2;//2    short a3;//2}A;struct //sizeof(B)=8 !!!!{    long a1;//4    short a2;//2}B;class C //sizeof(C)=24{public:    double d;  //8  最长数据元素,作为对齐单位    //float 和 int连续存储在开辟的第二个8字节内存中    float f;  //4    int i;  //4    //short 和 char在第3个8字节内存中    short s;   //2    char c;   //1};class D  //sizeof(D)=4{    int a;  //4    //static变量放在全局数据区,而sizeof计算栈中分配的大小,故不会计算在内!!!    static int b;};class E  //sizeof(E)=12{private:    //由于数据对齐,第1个bool型先开辟4字节    bool a;  //1    //int型自己就占4个字节,作为对其单位为类中最长数据元素,再开辟4字节    int b;  //4    //第二个bool型接着开辟4字节    bool c;  //1};class F{private:  //sizeof(F)=8    int b;  //4    //2个bool类型都各占1个字节,因此都放到第2个4字节的内存中!!!!!    bool a;  //1    bool c;  //1};class G{};//空类所占的空间为1class G1{};class H: public G{};//单一继承的空类空间也为1class I: public virtual H{};//虚继承因涉及到虚表(虚指针),所占的空间为4!!!class J: public G,public G1{};//多重继承的空类空间也为1int main(void){    char* ss1 = "0123456789"; //字符指针,指针的大小是定值,4字节!!!!!    int * ss11; //4    //字符数组,最初未定大小,由具体填充值来定,填充值为10字符,1个字符    //1字节,共10字节,加上“\0”,共11字节!!!!!    char ss2[] = "0123456789";//11    char ss3[100] = "0123456789";//字符数组,100 * 1=100    int ss4[100];//整型数组,100*4=400    char q1[]="abc";//4    char q2[]="a\n";//3    char* q3="a\n";//4    char *str1 = (char*)malloc(100);//指针固定为4    void *str2 = (void*)malloc(100);//指针固定为4    C c;    cout<<"sizeof(ss1)="<<sizeof(ss1)<<endl;    cout<<"sizeof(ss11)="<<sizeof(ss11)<<endl;    cout<<"sizeof(ss2)="<<sizeof(ss2)<<endl;    cout<<"sizeof(ss3)="<<sizeof(ss3)<<endl;    cout<<"sizeof(ss4)="<<sizeof(ss4)<<endl;    cout<<"sizeof(q1)="<<sizeof(q1)<<endl;    cout<<"sizeof(q2)="<<sizeof(q2)<<endl;    cout<<"sizeof(q3)="<<sizeof(q3)<<endl;    cout<<"sizeof(A)="<<sizeof(A)<<endl;    cout<<"sizeof(A.a1)="<<sizeof(A.a1)<<endl;    cout<<"sizeof(B)="<<sizeof(B)<<endl;    cout<<"sizeof(B.a1)="<<sizeof(B.a1)<<endl;    cout<<"sizeof(C)="<<sizeof(C)<<endl;    cout<<"sizeof(c.d)="<<sizeof(c.d)<<endl;    cout<<"sizeof(c.f)="<<sizeof(c.f)<<endl;    cout<<"sizeof(D)="<<sizeof(D)<<endl;    cout<<"sizeof(E)="<<sizeof(E)<<endl;    cout<<"sizeof(F)="<<sizeof(F)<<endl;    cout<<"sizeof(G)="<<sizeof(G)<<endl;//空类所占的空间为1    cout<<"sizeof(H)="<<sizeof(H)<<endl;//单一继承的空类空间也为1    cout<<"sizeof(I)="<<sizeof(I)<<endl;//虚继承因涉及到虚表(虚指针),所占的空间为4    cout<<"sizeof(J)="<<sizeof(J)<<endl;//多重继承的空类空间也为1    cout<<"sizeof(str1)="<<sizeof(str1)<<endl;    cout<<"sizeof(str2)="<<sizeof(str2)<<endl;    return 0;}

执行结果:

sizeof(ss1)=4sizeof(ss11)=4sizeof(ss2)=11sizeof(ss3)=100sizeof(ss4)=400sizeof(q1)=4sizeof(q2)=3sizeof(q3)=4sizeof(A)=6sizeof(A.a1)=2sizeof(B)=8sizeof(B.a1)=4sizeof(C)=24sizeof(c.d)=8sizeof(c.f)=4sizeof(D)=4sizeof(E)=12sizeof(F)=8sizeof(G)=1sizeof(H)=1sizeof(I)=4sizeof(J)=1sizeof(str1)=4sizeof(str2)=4Process returned 0 (0x0)   execution time : 0.190 sPress any key to continue.

sizeof的使用场合:

a.查看某种类型的对象在内存中所占的单元字节b.动态分配一对象时,使系统知道要分配多少内存c.操作数的字节数在实现时可能出现变化,可用sizeof代替常量计算d.与存储分配和I/O系统那样的进程通信: void * malloc(size_t size); size_tfread(void *ptr,size_t size,size_t n,FILE * stream);

sizeof 和 strlen的区别:

a. sizeof 用来计算操纵数所占内存大小,strlen用来计算字符串长度。sizeof不是函数也不是一元运算符,是个类似于宏定义的特殊关键字。sizeof()括号内的内容在编译过程中不被编译,只是被替代为类型。strlen 的内部实现为:用一个循环计算字符串的长度,直到遇到“\0”为止。sizeof 可以看作算符,strlen是函数,故strlen后面必须加括号,而sizeof后面跟类型时需加括号,跟变量名时不需加括号。b.sizeof 可以用类型、变量名、甚至函数作参数,strlen只能用以“\0”结尾的char*作参数。char fun(); cout<返回值类型的大小c.sizeof的结果类型为size_t,它在头文件中被typedefunsigned intd.数组做参数传递给sizeof时不退化,传递给strlen时退化为指针e.unsigned影响的是最高位bit的意义,数据长度不会被改变f.一般在编译时就计算过sizeof了,运行时才知道strlen的结果。g.sizeof不能用于不完全类型或位字段。不完全类型是指具有未知存储大小数据的数据类型,如未知存储大小的数组、结构、联合以及void类型。

数组作为参数传递到函数内时,退化为一个指针

C++中类所占的存储空间:

类所占的空间 = 类成员变量所占空间 + 4(如果存在虚函数的话);

注意:

1、类成员所占的空间可能会涉及到内存数据对齐的问题,需要谨慎考虑;

  1)当成员变量的长度都小于处理器位数时,所有成员变量所占的总空间一定是最长的变量所占空间的整数倍;  2)如果某一成员变量长度大于处理器位数,则以处理器的位数为对齐单位;  关于数据对齐,详见:http://blog.csdn.net/tangbo1987/article/details/6766918

2、如果类成员函数不是虚函数,则它不占空间;

3、如果成员函数中存在虚函数,则所有的虚函数保存在虚函数表中,然后类中会有一个指针指向该表;这个指针需要占用空间,所以需要 +4;

此外,空类所占的空间为1字节,因为:

“一个类能够实例化,编译器就需给它分配内存空间,来指示类实例的地址;这里编译器默认分配了一个字节(如:char),以便标记可能初始化的类实例,同时使空类占用的空间也最少(即1字节)” –引用 http://blog.csdn.net/sunboy_2050/article/details/6589999

空结构体同理。

补充

有一个陷阱:

int *d = new int[10]; cout<<sizeof(d)<<endl; // 4

d是我们常说的动态数组,但是他实质上还是一个指针,所以sizeof(d)的值是4。

再考虑下面的问题:

double* (*a)[3][6];cout<<sizeof(a)<<endl; // 4cout<<sizeof(*a)<<endl; // 72cout<<sizeof(**a)<<endl; // 24cout<<sizeof(***a)<<endl; // 4cout<<sizeof(****a)<<endl; // 8
a是一个很奇怪的定义,他表示一个指向 double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。 既然a是执行double*[3][6]类型的指针,*a就表示一个double*[3][6]的多维数组类型,因此sizeof(*a)=3*6*sizeof(double*)=72。同样的,**a表示一个double*[6]类型的数组,所以sizeof(**a)=6*sizeof(double*)=24。***a就表示其中的一个元素,也就是double*了,所以sizeof(***a)=4。至于****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。 

对于string类型:

#include <iostream>//#include<string.h>using namespace std;int main(void){    string str1 = "hellohahaha";    string str2[] = {"trend", "micro", "soft"};    cout<<sizeof(str1)<<endl; //4 不论多长,一段就是4字节    cout<<sizeof(str2)<<endl; //12,包含3段,则是12    return 0;}

结果:

412Process returned 0 (0x0)   execution time : 0.148 sPress any key to continue.
0 0
原创粉丝点击