一、sizeof概念
sizeof()是一个操作符(operator),不是函数。
它的功能是返回一个对象或者类型名的长度,类型为size_t,单位为字节。
size_t是一个依赖编译器的值,定义在头文件stddef.h,一般定义为 typedef unsigned int size_t;
二、sizeof有三种语法:
(1)sizeof(object);//sizeof(对象);
(2)sizeof(type_name);//sizeof(类型);
(3)sizeof object;//sizeof 对象。
三、sizeof与strlen()比较
sizeof是操作符,strlen()是函数。
strlen()计算字符数组的字符数,以'\0'为结束判断,不计算为'\0'的数组元素。
而sizeof计算数据(包括数组、变量、类型、结构体等)所占内存空间,用字节数表示,包含'\0'所占空间。
eg1:
char str1[] = “Hello”;
sizeof (str1 ) = 6 (自动加了'\0')
strlen (str1 ) = 5 (字符串的长度)
char str2[5] = {'H','e','l','l','o'};
sizeof (str2 ) = 5 (字符数组的大小)
strlen (str2) = 未知 (该字符串缺少结束符'\0')
char str3[6] = {'H','e','l','l','o','\0'};
sizeof (str3) = 6 (字符数组的大小)
strlen (str3) = 5 (该字符串的长度为5)
sizeof:计算字符数组大小(包括’\0’)
strlen:计算长度,到’\0’为止
eg2:
char arr[10] = "Hello";
strlen(arr) = 5; //有效字符串长度为5.
sizeof(arr) = 10;//数组长度为10。
四、基本数据类型的sizeof
基本数据类型指short、int、long、float、double这样的简单内置数据类型,由于它们都是和系统相关的,所以在不同的系统下取值可能不同。一般的,在32位编译环境中:
sizeof(char) = 1;
sizeof(int) = 4;
sizeof(long) = 4;
sizeof(float) = 4;
sizeof(double) = 8.
五、指针类型的sizeof
指针用于存放地址,它等于计算机内部地址总线的宽度,所以32位计算机中,一个指针变量的返回值是4字节(与指针变量的类型无关)。可以预计,在64位系统中指针变量的sizeof等于8。
sizeof(p) = 4;
六、数组的sizeof
数组的sizeof值等于数组所占用的内存字节数,如:
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符串末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(3*sizeof(int))
数组元素个数的求法:
sizeof(a1)/sizeof(*a1);
当数组作为函数参数时将从数组类型蜕变为指针类型:
void Function1( char p[],int num ){
sizeof (p) = 4 ;//(数组在作为函数参数时均化为指针,p此时为char*类型)
}
七、联合体的sizeof
联合体在内存结构上是重叠式的,各成员共享一段内存,所以整个联合体的sizeof就是最大成员的sizeof值。
八、结构体的sizeof
结构体空间大小的计算遵循的原则是字节对齐。
类或者结构体的sizeof大小必须是类中最大数据类型的整数倍。
CPU访问对齐的数据的效率是最高的,因此通常编译浪费一些空间来使得我们的数据是对齐的。
总体上遵循两个原则:
1)整体空间是占用空间最大的成员(的类型)所占字节数的整倍数
2)数据对齐原则----内存按结构成员的先后顺序排列,当排到该成员变量时,其前面已摆放的空间大小必须是该成员类型大小的整倍数,如果不够则补齐,以此向后类推。举例如下:
struct s1{
char a;
short b;
int c;
char d;
};//sizeof(s1) = 12;
struct s2{
char a;
char b;
int c;
short d;
};//sizeof(s2)= 12.
s1中char占1个字节,short占2个字节,int占4个字节,因此结构体的自身对齐字节大小为4字节。于是a和b要组成4字节,以便与c的4字节对齐。其存储方式具体如下图:
其中空白方格无数据,是浪费的内存空间,共占用8字节内存。
s2的存储结构如下:
这里有个陷阱,对于结构体中的结构体成员,不要认为它的对齐方式就是他的大小,看下面的例子:
struct s1{
char a[9];
};//sizeof(s1) = 9;
struct s2{
double d;
};//sizeof(s2) = 8;
struct s3{
s1 s;
char a;
};//sizeof(s3) = 10;
struct s4{
s2 s;
char a;
};//sizeof(s4) = 16
s1的对齐方式是1(char),s2是8(double),所以在s3和s4中才有这样的差异。
还有一个影响sizeof的重要参量--编译器的pack指令。它是用来调整结构体对齐方式的,不同编译器名称和用法略有不同,VC6中通过#pragma pack实现,也可以直接修改/Zp编译开关。#pragma pack的基本用法为:#pragma pack( n ),n为字节对齐数,其取值为1、2、4、8、16,默认是8,如果这个值比结构体成员的sizeof值小,那么该成员的偏移量应该以此值为准,即是说,结构体成员的偏移量应该取二者的最小值,公式如下:
offsetof( item ) = min( n, sizeof( item ) )
eg:
#pragma pack(1)// 必须在结构体定义之前使用
struct s4{
char c;
int i;
};sizeof(s4) = 5;
#pragma pack(1),对齐值变为1,所以sizeof = 5。此时内存紧凑,不会出现内存浪费,但效率降低了。效率之所以降低,是因为:如果存在更大字节数的变量时(比1大),比如int类型,需要进行多次读周期才能将一个int数据拼凑起来。
九、类的sizeof(类似于结构体的sizeof)
1)多重继承
class A{};
class B{};
class C : public A, public B{};
class D : virtual public A{};
class E : virtual public A, virtual public B{};
sizeof(A) = 1,sizeof(B) = 1(空类大小为1,编译器安插一个char给空类,用来标记它的每一个对象)
sizeof ( C ) = 1 (继承或多重继承后空类大小还是1)
sizeof(D) = 4 (虚继承时编译器为该类安插一个指向父类的指针,指针大小为4)
sizeof(E) = 8 (指向父类A的指针与父类B的指针,加起来大小为8)
2)函数与虚函数
编译器为每个有虚函数的类都建立一个虚函数表(其大小不计算在类中),并为这个类安插一个指向虚函数表的指针,即每个有虚函数的类其大小至少为一个指针的大小4
class A {
public:
int a;
void Function();
};
class B {
public:
int a;
virtual void Function();
};
class C : public B{
public:
char b;
};
class D : public B{
public:
virtual void Function2();
/*
Int a; 继承来的
Vptr *p; 虚函数指针
*/
};
class E{
public:
static void Function();
};
class F{
static int a;
}
sizeof (A) = 4 (内含一个int,普通函数不占大小)
sizeof (B) = 8 (一个int ,一个虚函数表指针)
sizeof (C) =12 (一个int ,一个虚函数表指针,一个char ,再加上数据对齐)
sizeof (D) = 8 (一个int ,一个虚函数表指针,多个虚函数是放在一个表里的,所以虚函数表指针只要一个就行了)
sizeof (E) = 1 (static 函数不占大小,空类大小为1)
sizeof(F) = 1 (static数据成员不属于class所有)
static成员变量是存储在静态区当中的,它是一个共享的量,因此,在为这个类创建一个实例对象的时候,是无需再为static成员变量分配空间的,所以,这个类的实例对象所需要分配的空间是要排除static成员变量的,于是,当sizeof计算类的大小的时候会忽略static成员变量的大小。
3)父类的私有数据
虽然在子类中不可用,但是是可见的,因此私有的数据还是要占子类的大小
class A{
private:
int a;
};
class B:public A{};
sizof(B) = 4; (内含一个不可用的父类的int)
十、含有位域结构体的sizeof
参考文章:
http://blog.csdn.net/freefalcon/article/details/54839
http://blog.chinaunix.net/uid-26868581-id-3328170.html
http://blog.sina.com.cn/s/blog_715de2f50100pgs3.html
http://blog.chinaunix.net/uid-20726927-id-2455478.html