sizeof操作符

2015/05/06 C和C++基础

sizeof是一种单目操作符,而不是函数。sizeof操作符以字节形式给出了其操作数的存储空间。操作数可以是一个表达式或括在括号内的类型名。操作数的存储空间由操作数的类型决定。

13.填空题–使用sizeof计算普通变量所占的空间

在32位WinNT操作系统环境下,有如下代码:

char str[]="hello";
char *p=str;
int n=10;
sizeof(str)=_____;
sizeof(P)=_____;
sizeof(n)=_____;
void Func(char str[100]){
	sizeof(str)=____;
}
void *p=malloc(100);
sizeof(p)=_____;

解析:

str变量表示数组,n为整型数据,其他都表示为地址。数组最后一个元素保存字符串结束符,所以sizeof(str)=strlen(“Hello”)+1。对于指针,无论是何种类型的指针,其大小都是固定的。

答案:

6 4 4 4 4

14.分析代码写结果–使用sizeof计算类对象所占空间大小

请写出下面程序在32位WinNT操作系统环境下的输出是什么?

#include <iostream>

using namespace std;

class A{
public:
	int i;
};

class B{
public:
	char ch;
};

class C{
public:
	int i;
	short j;
};

class D{
public:
	int i;
	short j;
	char ch;
};

class E{
public:
	int i;
	int ii;
	short j;
	char ch;
	char chr;
};

class F{
	int i;
	int ii;
	int iii;
	short j;
	char ch;
	char chr;
};


int main(){
	cout<<"sizeof(int)="<<sizeof(int)<<endl;        //4
	cout<<"sizeof(short)="<<sizeof(short)<<endl;    //2
	cout<<"sizeof(char)="<<sizeof(char)<<endl;      //1
	cout<<endl;
	cout<<"sizeof(A)="<<sizeof(A)<<endl;            //4
	cout<<"sizeof(B)="<<sizeof(B)<<endl;            //1
	cout<<"sizeof(C)="<<sizeof(C)<<endl;            //8
	cout<<"sizeof(D)="<<sizeof(D)<<endl;            //8
	cout<<"sizeof(E)="<<sizeof(E)<<endl;            //12
	cout<<"sizeof(F)="<<sizeof(F)<<endl;            //16

	system("pause");
}

类和结构体一样,要考虑内存字节对齐。

15.分析代码写结果–使用sizeof计算含有虚函数的类对象的空间大小
#include <iostream>

using namespace std;

class Base{
public:
	Base(int x):a(x){}
	void print(){
		cout<<"base"<<endl;
	}
private:
	int a;
};

class Derived:public Base{
public:
	Derived(int x):Base(x-1),b(x){};
	void print(){
		cout<<"derived"<<endl;
	}
private:
	int b;
};

class A{
public:
	A(int x):a(x){};
	virtual void print(){
		cout<<"A"<<endl;
	}
private:
	int a;
};

class B:public A{
public:
	B(int x):A(x-1),b(x){}
	virtual void print(){
		cout<<"B"<<endl;
	}
private:
	int b;
};


int main(){
	Base obj1(1);
	cout<<"size of Base obj is"<<sizeof(obj1)<<endl;       //4
	Derived obj2(2);
	cout<<"size of Derived obj is"<<sizeof(obj2)<<endl;    //8

	A a(1);
	cout<<"sizeof of A obj is"<<sizeof(a)<<endl;           //8
	B b(2);
	cout<<"sizeof of A obj is"<<sizeof(b)<<endl;           //12
	system("pause");
}

程序解析:

对于Base类来说,sizeof(int)等于4,print()函数不占内存;

对于Derived类来说,比Base类多了一个整型成员,因而多4字节,一共是8字节;

对于A类来说,由于它含有虚函数,因此占用内存除了一个整型变量之外,还包括一个隐含的虚表指针成员,一共是8字节;

对于B类来说,比A类多了一个整型成员,因而多了4字节,一共是12字节;

普通函数不占用内存,只有虚函数会占用一个指针大小的内存,原因是系统用一个指针维护这个类的虚函数表,并且要注意这个虚函数无论含有多少项(类中含有多少个虚函数)都不会影响类的大小

有虚函数的类也遵循内存字节对齐规则:

#include <iostream>

using namespace std;

class A{
public:
	A(int x):a(x){};
	virtual void print(){
		cout<<"A"<<endl;
	}

private:
	char a;
	char b;
};

int main(){
	A a(1);
	cout<<"sizeof of A obj is"<<sizeof(a)<<endl;           //8
	system("pause");
}
#include <iostream>

using namespace std;

class A{
public:
	A(int x):a(x){};

private:
	char a;
public:
	virtual void print(){
		cout<<"A"<<endl;
	}
private:
	char b;
};

int main(){
	A a(1);
	cout<<"sizeof of A obj is"<<sizeof(a)<<endl;           //8
	system("pause");
}
#include <iostream>

using namespace std;

class A{
public:
	A(int x):a(x){};
	virtual void print(){
		cout<<"A"<<endl;
	}
	virtual void print1(){
		cout<<"A1"<<endl;
	}

private:
	char a;
	char b;
};

int main(){
	A a(1);
	cout<<"sizeof of A obj is"<<sizeof(a)<<endl;           //8
	system("pause");
}
分析代码写结果–使用sizeof计算虚继承类的类对象的空间大小
#include <iostream>

using namespace std;

class A{

};

class B{

};

class C:public A,public B{

};

class D:virtual public A{

};

class E:virtual public A,virtual public B{

};

class F{
public:
	int a;
	static int b;
};

int F::b=10;

int main(){
	//注意sizeof(A)是测量A示例化以后的大小 
	//比如 Class A; A obj; 那么sizeof(A)==sizeof(obj)

	//实例化==类创建对象  实例==对象
	//对象和结构体一样 对象的地址和对象成员的首地址一样
	F fobj;
	cout<<&fobj<<"  "<<&fobj.a<<endl;  

	cout<<"sizeof(A)="<<sizeof(A)<<endl;  //1
	cout<<"sizeof(B)="<<sizeof(B)<<endl;  //1
	cout<<"sizeof(C)="<<sizeof(C)<<endl;  //1
	cout<<"sizeof(D)="<<sizeof(D)<<endl;  //4
	cout<<"sizeof(E)="<<sizeof(E)<<endl;  //8
	cout<<"sizeof(F)="<<sizeof(F)<<endl;  //4
	system("pause");
}

当类实例化成对象会在内存中分配空间,对象的地址就是对象第一个数据成员的首地址。但是空类实例化成对象时,该对象并没有数据成员,因此编译器会给空类插入一个char字节变量,该char字节变量的地址就是空类对象在内存中的地址。因此A实例化以后大小为1个字节;

实例化B大小和A相同,都是1字节;

类C多继承自A和B,大小仍然为1字节;

类D是虚继承自A,编译器为该类安插一个指向父类的指针,指针大小为4,由于此类有了指针,编译器不会安插一个char,因此其大小为4字节;

类E虚继承自A并且也虚继承自B,因此它有指向父类A的指针和父类B的指针,加起来大小为8字节。

类F含有一个静态成员变量,这个静态成员变量的空间不在类实例中,而是像全局变量一样在静态存储区中,被类共享,因此其大小是4字节。

17.sizeof与strlen有哪些区别

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

2.sizeof操作符的结果类型时size_t,它在头文件中typedef为unsigned int类型,该类型保证能容纳实现所建立的最大对象的字节大小。

3.sizeof可以用类型做参数,strlen只能用char*作参数,且必须是以“\0”结尾。

4.数组做sizeof的参数不退化,但是传递给strlen就退化为指针。

5.大部分编译程序在编译的时候sizeof就被计算过了,这就是sizeof(x)可以用来定义数组维数的原因。strlen的结果要在运行的时候才能计算出来,它用来计算字符串的长度,不是类型占内存的大小

6.sizeof后如果是类型必须加括弧,如果是变量名可以不加括弧,这是因为sizeof是个操作符不是函数。

7.在计算字符串数组的长度上有区别。例如:

char str[20]="0123456789";
int a=strlen(str);  //10
int b=sizeof(str);  //20

8.如果要计算指针指向的字符串的长度,则一定要使用strlen,例如:

char* ss="0123456789";
int a=sizeof(ss);  //4   指针占用内存空间的大小
int b=strlen(ss);  //10
18.sizeof有哪些用途?

1.查看某个类型的对象在内存中所占的单元字节数;

2.动态分配对象时,可以使系统知道要分配多少内存;

19.找错–使用strlen()函数代替sizeof计算字符串长度
#include <iostream>
#include <string>
using namespace std;

void UpperCase(char str[]){
	int test=sizeof(str);         //4
	int test2=sizeof(str[0]);     //1
	for(size_t i=0;i<sizeof(str)/sizeof(str[0]);i++){
		if('a'<=str[i]&&str[i]<='z')
			str[i]-=('a'-'A');    //化为大写字母
	}
}

int main(){
	char str[]="aBcDe";
	cout<<"The length of str is"<<sizeof(str)/sizeof(str[0])<<endl;     //6
	UpperCase(str);
	cout<<str<<endl;
	return 0;
}

改正:

#include <iostream>
#include <string>
using namespace std;

void UpperCase(char str[]){
	int test=sizeof(str);         //4
	int test2=sizeof(str[0]);     //1
	for(size_t i=0;i<strlen(str);i++){
		if('a'<=str[i]&&str[i]<='z')
			str[i]-=('a'-'A');    //化为大写字母
	}
}

int main(){
	char str[]="aBcDe";
	cout<<"The length of str is"<<strlen(str)<<endl;     //5
	UpperCase(str);
	cout<<str<<endl;
	return 0;
}
20.分析代码写结果–使用sizeof计算联合体的大小
#include <iostream>

using namespace std;

union u{
	double a;
	int b;
};

union u2{
	char a[13];
	int b;
};

union u3{
	char a[13];
	char b;
};

int main(){
	cout<<sizeof(u)<<endl;   //8
	cout<<sizeof(u2)<<endl;  //16
	cout<<sizeof(u3)<<endl;  //13
	system("pause");
}
#include <iostream>

using namespace std;

#pragma pack(2)

union u{
	char buf[9];
	int a;
};

int main(){
	cout<<sizeof(u)<<endl;   //10
	system("pause");
}
21.#pragma pack的作用
#include <iostream>

using namespace std;

#pragma pack(1)

struct test{
	char c;
	short s1;
	short s2;
	int i;
};

int main(){
	cout<<sizeof(test)<<endl;   //9
	system("pause");
}
sizeof(i++)
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int i;
	i = 10;
	printf("%d\n", i);              //10
	printf("%d\n", sizeof(i++));    //4
	printf("%d\n", i);              //10
	system("pause");
}

解析:

如果sizeof的操作数是一个表达式的话,这个表达式时不会被计算的。

继承类的sizeof
#include <iostream>

using namespace std;

class A{
public:
	A(int a):n(a){}
	int n;
};

class B:public A{
public:
	B(int a,int b):A(a),nn(b){}
	int nn;
};


int main(){
	cout<<sizeof(A)<<endl;   //4
	cout<<sizeof(B)<<endl;   //8
	system("pause");
}
#include <iostream>

using namespace std;

class A{
public:
	A(int a):n(a){}
	int n;
};

class B:public virtual A{
public:
	B(int a,int b):A(a),nn(b){}
	int nn;
};


int main(){
	cout<<sizeof(A)<<endl;   //4
	cout<<sizeof(B)<<endl;   //12  算上虚继承涉及虚表(虚指针)
	system("pause");
}
#include <iostream>

using namespace std;

class A{
public:
	A(int a):n(a){}
	int n;
	virtual void get(){
		cout<<n<<endl;
	}
};

class B:public virtual A{
public:
	B(int a,int b):A(a),nn(b){}
	int nn;
};


int main(){
	cout<<sizeof(A)<<endl;   //8   虚函数表指针 该变量不能继承
	cout<<sizeof(B)<<endl;   //16  算上虚继承涉及虚表(虚指针)
	system("pause");
}

Search

    Post Directory