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");
}