1. 基本类型的sizeof:
cout << "char: " << sizeof(char) << endl;
cout << "int: " << sizeof(int) << endl;
cout << "unsigned int: " << sizeof(unsigned int) << endl;
cout << "long(long int/long long):" << sizeof(long) << endl;
cout << "short(short int): " << sizeof(short int) << endl;
cout << "float: " << sizeof(float) << endl;
cout << "double: " << sizeof(int) << endl;
运行结果:
char: 1
int: 4
unsigned int: 4
long(long int/long long):8
short(short int): 2
float: 4
double: 4
2. 指针类型的sizeof:
指针类型的sizeof需要先明确它是代表什么,代表指针,则其值为8,因为指针本身占用8字节的长度,如果指向的是类型或对象,则根据指向的类型或对象分析。
const char *p = "123";
cout << "The sizeof of Point:" << sizeof(p) << endl;
cout << "THe sizeof of char :" << sizeof(*p) << endl;
int *p1 = new int(1);
cout << "The sizeof of Point:" << sizeof(p1) << endl;
cout << "The sizeof of int :" << sizeof(*p1) << endl;
const char **p2 = &p;
cout << "The sizeof of Point:" << sizeof(p2) << endl;
cout << "The sizeof of Point:" << sizeof(*p2) << endl;
cout << "The sizeof of char :" << sizeof(**p2) << endl;
void* (*pf)();
cout << "The sizeof of Function Point:" << sizeof(pf) << endl;
下面为结果,前面都有解释输出的是什么:
The sizeof of Point:8
THe sizeof of char :1
The sizeof of Point:8
The sizeof of int :4
The sizeof of Point:8
The sizeof of Point:8
The sizeof of char :1
The sizeof of Function Point:8
3. 数组类型的sizeof:
数组类型的sizeof等于它所占的字节,即元素个数*每个元素的sizeof。
const char ch[] = "ABC";
cout << "The sizeof of array:" << sizeof(ch) << endl;
输出的结果是4,解释一下,这是由于"ABC"是"ABC\0"这样的常量数组,所以其sizeof为1*4 = 4.
The sizeof of array:4
4. 结构体的sizeof:
结构体的sizeof比较复杂,其实懂的话也就不难了。我这里也不做那么深入的解释,其实我也不怎么会。
先不看位域结构体以及含有pack的结构体,看普通含有基本类型的结构体先:
struct node
{
char c;
double d;
int a;
}a;
sizeof(a)=24,你可能会很好奇,为什么等于24呢?不应该是1+8+4=13,需要符合4的倍数,所以sizeof(a)=16,不应该是16吗?其实不是这么算的。
首先是char,其占用一个字节,即大小=1,偏移量=1
其次是double,其占用8个字节,而此时偏移量为1,不满足是sizeof(double)的倍数,所以偏移量从8开始,之前空出来的全部补0,这时候,大小=16,偏移量=16
最后是int,其占用4个字节,而此时偏移量为16,满足sizeof(int)的倍数,此时,大小=20,偏移量=20。
最后,整个结构体的大小需要满足最大元素的倍数,即为8的倍数,此时,大小就变成了24。
那么下面的结构体大小是多少呢?
struct node
{
char c;
int a;
double d;
}a;
没错,sizeof(a)=16
之后,再看一个含有pack的结构体:
#pragma pack(push) //保存对齐状态
#pragma pack(4) //设定为4字节对齐
struct node
{
int c;
double d;
int a;
}a;
#pragma pack(pop)
那么这样sizeof(a)的大小就是16。
最后就是位域结构体:
struct node
{
char f1:3;
char f2:4;
char f3:5;
}a;
这个sizeof(a)是多少呢?答案是2。位域的意义在于提示编译器这个占几位,一字节有8位,而f1占了3位,f2占了4位,f3占了5位,那么就需要两字节来存储这个结构体,答案就是2。
5. 结构体内嵌:
struct A
{
int a;
int b;
int c;
}b;
struct node
{
char c;
A a;
}a;
此时sizeof(a)=16,为什么呢?结构体内部嵌套结构体时,内部结构体是按其内部元素的最大长度作为对齐标准的,也就是4。此时a.c之后的偏移量应该是4,4+12=16,16满足4的倍数,所以是16。
6. 内含联合体的结构体:
先看一下下面这个含有联合体的结构体:
struct node
{
char c;
union A
{
double a;
};
}a;
这个的大小和下面这个是否相同呢?
struct node
{
char c;
union A
{
double a;
}a;
}a;
答案是不一样的,第一个sizeof的大小为1,第二个大小为16,为什么呢!第一个的联合体是没有在结构体内部声明变量的,也就是说他只是一个声明而已,而第二个是又在里面定义的!这就导致了大小的不同。
此外,union里面的元素和struct没啥区别。
7. 内含枚举的结构体:
struct node
{
char c;
enum name
{
ABC=1,DEF=2,HIJ=3
};
}a;
上面这个和下面这个是否相同呢?
struct node
{
char c;
enum name
{
ABC=1,DEF=2,HIJ=3
}a;
}a;
其实和union是一样的!没有定义枚举的实例就不会占用内存。而且枚举所占用的内存都是4,无论里面有多少东西。
8. 类的sizeof:
这个比上面那些都要复杂,学完之后再来总结。(包括虚函数,虚继承带来的开销)
9. 最后,来一题过去阿里笔试题:
#pragma pack(push)
#pragma pack(2)
class A
{
int i;
union U
{
char buff[13];
int i;
}u;
void foo(){}
typedef char* (*f)(void *);
enum name
{
red,green,blue
}color;
}a;
#pragma pack(pop)
答案是22。
为什么呢?
首先是int,占4个字节。
然后联合体,记住联合体占的内存只与最长的一样,即为13,这里强制以2字节对齐,就是14字节。
下面那些没用,看到枚举,一个枚举无论里面有什么都是4。
所以结果为4+14+4 = 22,满足以2对齐的要求,所以答案是22。
参考网站:
https://blog.csdn.net/freefalcon/article/details/54839
https://www.cnblogs.com/x_wukong/p/5743369.html
https://blog.csdn.net/jollyhope/article/details/1895357
https://blog.csdn.net/michaelrun/article/details/1821529
https://www.cnblogs.com/shrimp-can/p/5171110.html