1、有一个如下的结构体:
struct A{
long a1;
short a2;
int a3;
int *a4;
};
请问在64位编译器下用sizeof(struct A)计算出的大小是多少?(24)
8 + 2 + 4 + 8 = 22, 对齐为8的倍数:24
32位编译器:32位系统下指针占用4字节
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器:64位系统下指针占用8字节
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
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{};//空类所占的空间为1
class G1{};
class H: public G{};//单一继承的空类空间也为1
class I: public virtual H{};//虚继承因涉及到虚表(虚指针),所占的空间为4!!!
class J: public G,public G1{};//多重继承的空类空间也为1
int 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)=4
sizeof(ss11)=4
sizeof(ss2)=11
sizeof(ss3)=100
sizeof(ss4)=400
sizeof(q1)=4
sizeof(q2)=3
sizeof(q3)=4
sizeof(A)=6
sizeof(A.a1)=2
sizeof(B)=8
sizeof(B.a1)=4
sizeof(C)=24
sizeof(c.d)=8
sizeof(c.f)=4
sizeof(D)=4
sizeof(E)=12
sizeof(F)=8
sizeof(G)=1
sizeof(H)=1
sizeof(I)=4
sizeof(J)=1
sizeof(str1)=4
sizeof(str2)=4
Process returned 0 (0x0) execution time : 0.190 s
Press any key to continue.
sizeof的使用场合:
a.查看某种类型的对象在内存中所占的单元字节
b.动态分配一对象时,使系统知道要分配多少内存
c.操作数的字节数在实现时可能出现变化,可用sizeof代替常量计算
d.与存储分配和I/O系统那样的进程通信: void * malloc(size_t size); size_t
fread(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,它在头文件中被typedef为unsigned int
d.数组做参数传递给sizeof时不退化,传递给strlen时退化为指针
e.unsigned影响的是最高位bit的意义,数据长度不会被改变
f.一般在编译时就计算过sizeof了,运行时才知道strlen的结果。
g.sizeof不能用于不完全类型或位字段。不完全类型是指具有未知存储大小数据的数据类型,
如未知存储大小的数组、结构、联合以及void类型。
数组作为参数传递到函数内时,退化为一个指针
C++中类所占的存储空间:
类所占的空间 = 类成员变量所占空间 + 4(如果存在虚函数的话);
注意:
1、类成员所占的空间可能会涉及到内存数据对齐的问题,需要谨慎考虑;
1)当成员变量的长度都小于处理器位数时,所有成员变量所占的总空间一定是最长的变量所占空间的整数倍;
2)如果某一成员变量长度大于处理器位数,则以处理器的位数为对齐单位;
关于数据对齐,详见:http://blog.youkuaiyun.com/tangbo1987/article/details/6766918
2、如果类成员函数不是虚函数,则它不占空间;
3、如果成员函数中存在虚函数,则所有的虚函数保存在虚函数表中,然后类中会有一个指针指向该表;这个指针需要占用空间,所以需要 +4;
此外,空类所占的空间为1字节,因为:
“一个类能够实例化,编译器就需给它分配内存空间,来指示类实例的地址;这里编译器默认分配了一个字节(如:char),以便标记可能初始化的类实例,同时使空类占用的空间也最少(即1字节)” –引用 http://blog.youkuaiyun.com/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; // 4
cout<<sizeof(*a)<<endl; // 72
cout<<sizeof(**a)<<endl; // 24
cout<<sizeof(***a)<<endl; // 4
cout<<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;
}
结果:
4
12
Process returned 0 (0x0) execution time : 0.148 s
Press any key to continue.
本文探讨了在面试中常见的sizeof运算符的应用。在64位编译器下,一个特定结构体`struct A`的大小被计算为24字节。在32位编译器上,详细分析了sizeof的使用场景,包括数组退化为指针的情况,以及C++类占用空间的计算规则,特别是涉及虚函数时的影响。类中虚函数表的指针占用4字节空间,而空类和空结构体则占用1字节以标记其地址。最后提到了动态数组和string类型的sizeof运算的特殊性。

被折叠的 条评论
为什么被折叠?



