sizeof用法总结

sizeof用法总结:

例子1:

<span style="font-size:18px;">int main(int argc, char *argv[])
{
	char *ss = "0123456789";
	cout<<sizeof(ss)<<endl;      //结果为4,ss是指向字符串常量的字符指针,类型为指针。
	cout<<sizeof(*ss)<<endl;     //结果为1,*ss是字符串的第一个字符,类型为char。
	return 0;
}</span>


例子2:

<span style="font-size:18px;">int main(int argc, char *argv[])
{
	char ss[] = "0123456789";
	cout<<sizeof(ss)<<endl;     //结果为11,ss为数组,计算到数组末尾的"\0",共11个字符。 
	cout<<sizeof(*ss)<<endl;    //结果为1,*ss同样是字符串的第一个字符。
	return 0;
}</span>


例子3:

<span style="font-size:18px;">int main(int argc, char *argv[])
{
	char ss[100] = "0123456789";
	cout<<sizeof(ss)<<endl;       //结果为100,ss数组在内存中分配了100个char类型的空间
	cout<<strlen(ss)<<endl;       //结果为10,计算字符串的长度,知道"\0"为止,这里字符数组类型转换为char*
	return 0;
}</span>


例子4:
<span style="font-size:18px;">int main(int argc, char *argv[])
{
	int ss[100] = {0,1,2,3,4,5,6,7,8,9};
	cout<<sizeof(ss)<<endl;      //结果为400,ss数组在内存中分配了100个int类型的空间
	cout<<strlen(ss)<<endl;      //错误,strlen参数只能是char*,而且是以"\0"结尾的
	return 0;
}</span>


例子5:
<span style="font-size:18px;">class X
{
	int i;
	int j;
	char k;
};
int main(int argc, char *argv[])
{
	X x;
	cout<<sizeof(x)<<endl;    //结果为12,x的类型为X
	cout<<sizeof(X)<<endl;    //结果为12,4+4+1补3,内存补齐,具体详情参考上一篇博文
	return 0;
}</span>

sizeof 与strlen 比较总结:

1. sizeof是运算符,strlen是函数

2. sizeof运算符的操作结果是size_t,它在头文件中的typedef为 unsigened int 类型,

3. sizeof可以用类型做参数,strlen只能用char *做参数,且字符串末尾必须以“\0”结尾。sizeof还可以以函数作参数,比如:

<span style="font-size:18px;">short f()
printf("%d\n",sizeof(f())); //实际为sizeof(short),结果为2</span>
4.数组做sizeof的参数不退化,传递给strlen就退化成char*指针,数组作为参数传给函数时传的是指针而不是数组,该指针指向数组的首地址,如fun(char[8]),func(char[])都等价于fun(char*)。编译器不知道数组的大小,如果函数想要知道数组的大小,需要这样做:

<span style="font-size:18px;">func(unsigned char *p1,int len)
{
    unsigned char *buff = new unsigned char[len+1];
    memcpy(buf,p1,len);
<span style="font-family: Arial, Helvetica, sans-serif;">}</span></span>
<span style="font-size:18px;">//例题:
char var[10];
int test(char var[])
{
    return sizeof(var); var[]等价于var*,已经退化成为指针了,指针的大小输出为4.
}</span>
5. 大部分编译器在编译的时候就把sizeof计算出来了,所以sizeof(x)可以直接用来定义数组的维数。而strlen的结果要在运行的时候才能计算出来,用来计算字符串的长度,而不是计算类型或变量占内存的大小。

<span style="font-size: 18px;">char str[20] = "0123456789";
int a = strlen(str);   //a=10
int b[sizeof(str)] ;   //b是维度为20的int型数组</span>
6 .sizeof后如果是类型必须加括号,如果是变量可不用加括号,这是因为sizeof是操作符,而不是函数。

7.sizeof()不是括号里的内容是不被编译的,而是被类型替代,如int a = 8;sizeof(a)在编译过程中,只是被替换成sizeof(int),结果为4,同样,sizeof(a=6)执行后,a的值还是为8不变。


8.unisgned 影响的只是最高位bit的意义,数据长度是不会改变的,所以sizeof(unsigned int) = sizeof(int).


9.自定义的类型sizeof取值等于它的类型原形:typedef short WORD,sizeof(WORD)== sizeof(short)


10.对函数使用sizeof,在编译期间会被函数的返回值类型替代。


11.只要是指针,sizeof计算的大小就是4。


12.数组的大小是各维数的乘积*数组元素的大小。


sizeof计算类的大小:

类的sizeof大小一般是类中的所有成员的sizeof大小之和,这个就不用多说。不过有几点需要注意:

1)当类中含有虚成员函数的时候,例如:

<span style="font-size:18px;">class B
{
     float a;
     public:
     virtual void fun(void);
}</span>
此时sizeof(B)的大小为8,而不是4。因为在类中隐藏了一个指针,该指针指向虚函数表,正因为如此,
使得C++能够支持多态,即在运行时绑定函数的地址。


2)另一个要注意的是,当类中没有任何成员变量,也没有虚函数的时候,该类的大小是多少呢?例如:

<span style="font-size:18px;">class B2
{
      void fun(void);
}</span>
此时sizeof(B2)的值是多少呢?在C++早期的编译器中,这个值为0;然而当创建这样的对象时,它们与紧接着它们后面的对象有相同的地址。比如:
B2 b2;
int a;
那么对象b2与变量a有相同的地址,这样的话对对象b2地址的操作就会影响变量a。所以在现在大多数编译器中,该值的大小为1。


3)类中的静态成员、及普通成员函数是不算入类的内存大小的

<span style="font-size:18px;">class A
{
    int print();
    int b;
    const int c;
    static int d;    
};</span>
此时sizeof(A)的大小为8,分别为b和c的变量之和

4)在类的继承中,如果是普通继承,子类的大小是子类的大小加上其所父类的大小之和,如果是虚继承,除了加上父类的大小,还需要计算指向父类的虚指针大小。


实例如下:

<span style="font-size:18px;">class A
{
    int virtual aa(){};
    char a;
    const int c;
    static int d;
};
class B : public   A
{
   char j[3];  
public:
   int virtual bb(){};
};
class C : public virtual B
{
   char i[3];
public:
   int virtual cc(){};
};
int main()  
{  
   cout<<sizeof(A)<<endl;   //结果为12
   cout<<sizeof(B)<<endl;   //结果为16
   cout<<sizeof(C)<<endl;   //结果为28
   return 0;  
} </span>
sizeof(A):虚函数指针(4)+ char型成员(原为1,位数补齐为4) + const int 型成员(4)  合计12

sizeof(B):char型数组(原为3,位数补齐为4) + 父类A的大小 (12) 合计16,需要注意的是,这里面B类中的虚函数和其父类的虚函数共用一个虚表,因此只用计算父类指向虚函数的指针,子类中忽略这一项。

sizeof(C):这里是虚拟继承,子类不与父类公用虚函数表,因此子类的指针需要单独计算,char型数组(4)+ 虚函数指针(4)+ 虚基类偏移量表指针(4)+ 父类的大小(16) 合计28


以下部分引用自:http://blog.csdn.net/jhj735412/article/details/7580498

类中各种情况下内存大小计算总结:

1.普通单继承,只需将自身成员变量的大小加上父类大小(父类中 有虚函数,子类中不管有没有)若父类没有虚函数,则子类大小需要加上指向虚表的指针大小。

2.普通多继承,若几个父类都有虚表,则子类与第一个父类公用一个虚表指针,其他有几个有虚函数的父类则就有几个虚表指针。

3.虚拟单继承,此时若子类有虚函数则加上一个自身的虚表指针的大小,(若没有则不加)再加上自身的成员变量大小,还要加上一个虚类指针ptr_sonclass_fatherclass,最后加上父类的大小。

4.多重虚拟继承,此时若子类有虚函数则加上一个自身的虚表指针的大小,(若没有则不叫)再加上自身的成员变量大小,还要加上 一个公用的虚类指针(不管有几个虚拟父类,只加一个),在加上所有父类的大小。

5.普通、虚拟混合多继承,此时子类的大小为自身大小(若子类或普通父类有虚函数,则为成员变量+虚表指针大小;若都没虚函数,则就为成员变量大小),加上一个虚类指针大小,在加上虚拟父类的大小,在加上普通父类的大小(除虚表指针,因为它和子类公用一个虚表指针)。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值