sizeof十大特性
- 是运算符,不是函数(操作数的概念)
- 不能求得void类型的长度
- 能求得void类型指针的长度
- 能求得静态分配内存的数组的大小
- 不能求得动态分配的内存大小
- 不能对不完整的数组求长度
- 表达式作为sizeof的操作数时,返回表达式的计算结果的类型大小,但是不对表达式求值。
- 可以对函数调用求大小,并且求得的大小等于返回类型的大小,但是不执行函数体
- 求得的结构体(对象)的大小并不等于各个数据成员对象的大小之和。
- 不能用于求结构体的位域成员的大小,但是可以求得包含位域成员的结构体的大小。
对于sizeof相关,进行了详细全面的整理。并通过代码进行了测试。
/*一.sizeof usage:
(1)sizeof(type|var) 考虑的是开辟的空间,不是用到的空间,对于结构体,需要考虑字节对齐的问题。
(2)对位域成员等连编译器都无法确定存储空间的东西不能用,不能使用于函数类型、不完全类型(具有未知存储大小的数据结构)或位字段。
(3)sizeof返回的数据类型是unsigned int
(4)要注意数组名和指针变量的区别。通常情况下,我们总觉得数组名和指针变量差不多,但是在用sizeof的时候差别很大,
对数组名用sizeof返回的是整个数组的大小,而对指针变量进行操作的时候返回的则是指针变量本身所占得空间,在32位机的条件下一般都是4。
而且当数组名作为函数参数时,在函数内部,形参也就是个指针,所以不再返回数组的大小
(5)union:不能定义static,最大的类型取sizeof,struct、class,需要考虑字节对齐问题,根据最长的来计算。
*/
#pragma pack(3)//表示补充的是空的元素,3是无效的数值,1、2、4、8等有效;
//#pragma pack (n) 虽然指定了按照N个字节对齐,但是当结构体内部,默认用m对齐的,而且m<n,n那么这个结构体就按照m个字节对齐而不是n字节对齐。
struct
{
char b;
double c;
int x;
double t;
static double d;//结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。
}a;
#pragma pack()
struct{
}s0;//没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一 个实例在内存中都有唯一的地址。
void testSizeof()
{
int iVal = 3;
//sizeof(void) sizeof(函数名) error
printf("The size of type struct is %d \n", sizeof(a));//4
printf("The size of type char is %d \n", sizeof(char));//1
printf("The size of type double is %d \n", sizeof(double));//8
printf("The size of type int is %d \n", sizeof(int));//4
printf("The size of iVal is %d\n", sizeof(iVal));//4
printf("The size of iVal is %d\n", sizeof iVal);//4
printf("(iVal - sizeof(int):%d\n",(iVal - sizeof(int)));
if((iVal - sizeof(int)) < 0)//当int和unsigned int一起运算时,会默认变成unsigned int,所以结果会是一个很大的unsigned int类型的数,是大于0的
{
printf("The return type is int\n");
}
else
{
printf("The return type is unsigned int\n");//print
}
char chArrayCon[7];
char *chp;
chp = chArrayCon;
printf("The size of chArrayCon is %d, The size of chp is %d\n", sizeof(chArrayCon), sizeof(chp));//7,4
const int iArraySize = 3;
char chArrayVar[iArraySize];
printf("The size of chArrayVar is %d\n", sizeof(chArrayVar));//3
//2 、other example
char str1[] = "Hello" ;
char str2[5] = {'H','e','l','l','o'};
char str3[6] = {'H','e','l','l','o','/0'};
char *p1 = "Hello";
char *p2[]={"hello","world"};
int n = 10;
int *q = &n;
sizeof (str1 );// = 6 (自动加了'/0')
strlen (str1 );// = 5 (字符串的长度)
sizeof (str2 );// = 5 (字符数组的大小)
strlen (str2);// = 未知 (该字符串缺少结束符'/0')
sizeof (str3);// = 6 (字符数组的大小)
strlen (str3);// = 5 (该字符串的长度为5)
sizeof ( p1 );// = 4 (p1是一个指针,大小为4)
sizeof ( p2 );// = 8 (p2是长度为2的字符串数组)
sizeof ( n );// = 4 (整型大小为4)
sizeof ( q );// = 4 (q是一个指针,大小为4)
//3、多重继承例子
/*
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 (空类大小为1,编译器安插一个char给空类,用来标记它的每一个对象)
sizeof ( B ) = 1 (空类大小为1,编译器安插一个char给空类,用来标记它的每一个对象)
sizeof ( C ) = 1 (继承或多重继承后空类大小还是1)
sizeof ( D ) = 4 (虚继承时编译器为该类安插一个指向父类的指针,指针大小为4)
sizeof ( E ) = 8 (指向父类A的指针与父类B的指针,加起来大小为8)
*/
//4 函数与虚函数
/*编译器为每个有虚函数的类都建立一个虚函数表(其大小不计算在类中),并为这个类安插一个指向虚函数表的指针,
即每个有虚函数的类其大小至少为一个指针的大小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();
};
class E{
public:
static void Function();
};
sizeof (A) = 4 (内含一个int,普通函数不占大小)
sizeof (B) = 8 (一个int ,一个虚函数表指针)
sizeof (C) =12 (一个int ,一个虚函数表指针,一个char ,再加上数据对齐)
sizeof (D) = 8 (一个int ,一个虚函数表指针,多个虚函数是放在一个表里的,所以虚函数表指针只要一个就行了)
sizeof (E) = 1 (static 函数不占大小,空类大小为1)
*/
}