c/c++整理--sizeof和strlen

一、使用sizeof计算普通变量所占空间大小

  计算结果:(假设32位win)

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测的是数组占的总内存大小,1x6 = 6;

  第五行,p测的是一个指针的大小,地址占4个字节,结果4

  第六行,n测的是int型数据大小,和指针一样,结果4

  第九行,函数是地址传递,str测到的还是指针大小,结果4

  第十二行,尽管十一行将p指向100字节的堆内存,但是测的还是指针大小,结果4


二、使用sizeof计算类对象所占空间大小

看代码写输出(win32)

#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
{
public:
	int i;
	int ii;
	int iii;
	short j;
	char ch;
	char chr;
};

int main()
{
	cout<<"sizeof(int) = "<<sizeof(int)<<endl;
	cout<<"sizeof(short) = "<<sizeof(short)<<endl;
	cout<<"sizeof(char) = "<<sizeof(char)<<endl;
	cout<<endl;
	cout<<"sizeof(A)"<<sizeof(A)<<endl;
	cout<<"sizeof(B)"<<sizeof(B)<<endl;
	cout<<"sizeof(C)"<<sizeof(C)<<endl;
	cout<<"sizeof(D)"<<sizeof(D)<<endl;
	cout<<"sizeof(E)"<<sizeof(E)<<endl;
	cout<<"sizeof(F)"<<sizeof(F)<<endl;
	
	return 0;
}

  这里要注意的是,对对象做sizeof运算时,不能简单地把各个成员所占的内存数相加,对象和结构体的内存分布有些相似,每个成员所占的内存大小不是由自身决定的,而是由当前结构体或者对象的占内存最大的成员决定,这样的内存分布最大的好处就是计算机每次读取数据的时候都只需读内存最大成员的大小,可以保证每个成员都只需读取一遍就可以读完,而不会出现读一次未完成,两次拼凑的情况,这样大大提高了计算机的读取效率。

所以:

  sizeof(int) = 4,sizeof(short) = 2, sizeof(char) = 1

  sizeof(A) = 4

  sizeof(B) = 1

  sizeof(C) = 4 + 4 = 8

  sizeof(D) = 4 + 2 + 2 = 8

  sizeof(E) = 4 + 4 + 2 + 1 + 1 = 12

  sizeof(F) = 4 + 4 + 4 + 2 + 1 + 1 = 16


三、使用sizeof计算含有虚函数的类对象的空间大小

看代码写输出

#include <iostream>

using namespace std;

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

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

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

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

int main()
{
	Base obj1(1);
	cout<<"sizeof(Base obj1) = "<<sizeof(obj1)<<endl;
	Derived obj2(2);
	cout<<"sizeof(Derived obj2) = "<<sizeof(obj2)<<endl;
	
	A a(1);
	cout<<"sizeof(A obj1) = "<<sizeof(a)<<endl;
	B b(2);
	cout<<"sizeof(B obj1) = "<<sizeof(b)<<endl;
	
	return 0;
}

  对于Base,占内存为4,print函数不占内存;对于Derived,占内存为8,因为继承于Base,所以有两个int数据,print不占内存。

  对于A类,由于有虚函数,因此占用的内存除了一个int型数据,还包括一个隐含的虚表指针成员,一个8个字节;

对于B类,比A类多一个int型数据,多四个字节,一共12个字节。

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


四、使用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 
{
	int a;
	static int b;
};

int main()
{
	cout<<"sizeof(A) = "<<sizeof(A)<<endl;
	cout<<"sizeof(B) = "<<sizeof(B)<<endl;
	cout<<"sizeof(C) = "<<sizeof(C)<<endl;
	cout<<"sizeof(D) = "<<sizeof(D)<<endl;
	cout<<"sizeof(E) = "<<sizeof(E)<<endl;
	cout<<"sizeof(F) = "<<sizeof(F)<<endl;
	
	return 0;
}

  A、B都是空类,编译器会安插一个char给空类,用来标记它的每个对象,因此其大小为1个字节,C多重继承A和B,大小也是1字节。D虚继承于A,编译器为给类安排一个指向父类的指针,大小为4,其总大小为4字节。E虚继承于A和B,有指向A的指针和B的指针,总大小8个字节。F有一个int,一个static int,static数据空间不在类实例中,而在程序的静态存储区,因此其大小为4个字节。


五、sizeof和strlen有哪些区别

区别如下:

(1)sizeof是操作符,strlen是函数。

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

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

(4)数组做sizeof的参数不退化,传递给strlen就退化为指针了。

(5)sizeof在编译的时候已经计算完毕了,所以sizeof可以测数据类型,strlen的结果在运行的时候计算,而且只是用来计算字符串长度,不能计算类型长度。

(6)sizeof后如果是类型,必须加括弧,如果是变量名,可以不加括弧。

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

char str[20] = "0123456789";
int a = strlen(str);
int b = sizeof(str);
a计算的是字符串的长度,为10

b计算的str【20】的内存空间,为20

(8)如果要计算指针指向的字符串长度,必须使用strlen


六、sizeof有哪些用途

(1)与存储分配和I/O系统那样的例程进行通信

(2)查看某个类型的对象在内存中所占的单元字节。

(3)在动态分配一对象时,可以让系统知道要分配多少内存。

(4)便于一些类型的扩充,在Windows中很多结构类型就有一个专门的字段是用来放该类型的字节大小。

(5)由于操作数的字节数在实现时可能出现变化,建议在涉及操作数字节大小时用sizeof来代替常量计算。

(6)如果操作数是函数中的数组形参或函数类型的形参,则sizeof给出其指针的大小。

七、使用sizeof计算联合体的大小

#include <iostream>

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;
	cout<<sizeof(u2)<<endl;
	cout<<sizeof(u3)<<endl;
	
	return 0;
}

联合体的大小取决于它所有的成员中占用空间最大的一个成员的大小,并且对于复合数据类型,如union、struct、class的对齐方式为成员中最大的成员对齐方式。

对于u,最大的是double a,所以sizeof(u) = sizeof(double) = 8

对于u2,最大的是char[13],这里要注意,由于另一个int b的存在,u2 的对齐方式变为4,也就是说,占用的空间会是一个4的倍数,大于13并最接近13的4的倍数就是16了

对于u3,最大的空间是char[13],sizeof(u3) = 13

8
16
13


八、#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;
	
	return 0;
}

#pragma pack(1)的作用就是将对齐方式设为1,sizeof(test ) = 1 + 2 + 2 + 4 = 9


  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值