# sizeof 知多少? （上）

## 0. 基本类型

sizeof(char) = 1(字节)

sizeof(short) = 2(字节)

sizeof(int) = 4(字节)

sizeof(pointer) = 4(字节)(其中pointer指代任意的指针类型)

## 1. 结构类型

```struct s1
{
int m_1;
};```

sizeof(s1)的大小是多少呢?很简单,对于只有单个成员的结构,其sizeof的大小便是其成员的sizeof大小,拿s1来说:

sizeof(s1) = sizeof(s1.m_1) = sizeof(int) = 4(字节)

```struct s1
{
int m_1;
int m_2;
int m_3;
};```

• 结构体 S 的大小等于 S 中各成员的大小之和 *

• sizeof(S) = sizeof(M1) + sizeof(M2) + … + sizeof(Mn) *

OK,既然有了公式,计算结构体的大小便简单了,仍然考虑之前的s1,我们稍稍改动一下他的定义(m_2成员由int类型改为了short类型):

```struct s1
{
int m_1;
short m_2;
int m_3;
};```

• sizeof(s1) = sizeof(s1.m_1) + sizeof(s1.m_2) + sizeof(s1.m_3) = sizeof(int) + sizeof(short) + sizeof(int) = 4 + 2 + 4 = 10(字节) *

```struct s1
{
int m_1;
short m_2;
int m_3;
};```

sizeof’(S, 0) = 0

sizeof’(S, i) = ceil(sizeof’(S, i - 1) / sizeof(Mi)) \ sizeof(Mi) + sizeof(Mi) (其中ceil为向上取整函数) *

sizeof’(s1, 0) = 0

sizeof’(s1, 1) = ceil(sizeof’(s1, 0) / sizeof(s1.m_1)) sizeof(s1.m_1) + sizeof(s1.m_1) = ceil(0 / 4) 4 + 4 = 4

sizeof’(s1, 2) = ceil(sizeof’(s1, 1) / sizeof(s1.m_2)) sizeof(s1.m_2) + sizeof(s1.m_2) = ceil(4 / 2) 2 + 2 = 6

sizeof’(s1, 3) = ceil(sizeof’(s1, 2) / sizeof(s1.m_3)) sizeof(s1.m_3) + sizeof(s1.m_3) = ceil(6 / 4) 4 + 4 = 12

sizeof’(s1, 3) = sizeof(s1) = 12

```struct s1
{
int m_1;
short m_2;
int m_3;
short m_4;
};```

sizeof’(s1, 0) = 0

sizeof’(s1, 1) = ceil(sizeof’(s1, 0) / sizeof(s1.m_1)) sizeof(s1.m_1) + sizeof(s1.m_1) = ceil(0 / 4) 4 + 4 = 4

sizeof’(s1, 2) = ceil(sizeof’(s1, 1) / sizeof(s1.m_2)) sizeof(s1.m_2) + sizeof(s1.m_2) = ceil(4 / 2) 2 + 2 = 6

sizeof’(s1, 3) = ceil(sizeof’(s1, 2) / sizeof(s1.m_3)) sizeof(s1.m_3) + sizeof(s1.m_3) = ceil(6 / 4) 4 + 4 = 12

sizeof’(s1, 4) = ceil(sizeof’(s1, 3) / sizeof(s1.m_4)) sizeof(s1.m_4) + sizeof(s1.m_4) = ceil(12 / 2) 2 + 2 = 14

sizeof’(s1, 4) = sizeof(s1) = 14

s[0]的各成员都是满足内存地址对齐的,但是由于结构s1的大小为14,这将导致s[1]的起始地址为14,遂而导致s[1]中的部分成员(譬如s[1].m_1)违反内存对齐原则…

sizeof’(S, 0) = 0

sizeof’(S, i) = ceil(sizeof’(S, i - 1) / sizeof(Mi)) \ sizeof(Mi) + sizeof(Mi) (其中ceil为向上取整函数) *

maxsizeof = max(sizeof(M1), sizeof(M2), …, sizeof(Mn)) (其中max为最大值函数)

sizeof(S) = ceil(sizeof’(S, n) / maxsizeof) \ maxsizeof *

## 2. 结构中的结构

```struct s1
{
int m_1;
short m_2;
int m_3;
short m_4;
};

struct s2
{
s1 m_1;
short m_2;
};```

sizeof’(s2, 0) = 0

sizeof’(s2, 1) = ceil(sizeof’(s2, 0) / sizeof(s2.m_1)) sizeof(s2.m_1) + sizeof(s2.m_1) = ceil(0 / 16) 16 + 16 = 16

sizeof’(s2, 2) = ceil(sizeof’(s2, 1) / sizeof(s2.m_2)) sizeof(s2.m_2) + sizeof(s2.m_2) = ceil(16 / 2) 2 + 2 = 18

maxsizeof = max(sizeof(s2.m_1), sizeof(s2.m_2)) = max(16, 2) = 16

sizeof(s2) = ceil(sizeof’(s2, 2) / maxsizeof) maxsizeof = ceil(18 / 16) 16 = 32

sizeof’(S, 0) = 0

sizeof’(S, i) = ceil(sizeof’(S, i - 1) / alignof(Mi)) \ alignof(Mi) + sizeof(Mi) (其中ceil为向上取整函数) *

maxalignof = max(alignof(M1), alignof(M2), …, alignof(Mn)) (其中max为最大值函数)

sizeof(S) = ceil(sizeof’(S, n) / maxalignof) \ maxalignof *

sizeof’(s2, 0) = 0

sizeof’(s2, 1) = ceil(sizeof’(s2, 0) / alignof(s2.m_1)) alignof(s2.m_1) + sizeof(s2.m_1) = ceil(0 / 4) 4 + 16 = 16

sizeof’(s2, 2) = ceil(sizeof’(s2, 1) / alignof(s2.m_2)) alignof(s2.m_2) + sizeof(s2.m_2) = ceil(16 / 2) 2 + 2 = 18

maxalignof = max(alignof(s2.m_1), alignof(s2.m_2)) = max(4, 2) = 4

sizeof(s2) = ceil(sizeof’(s2, 2) / maxalignof) maxalignof = ceil(18 / 4) 4 = 20

```struct s3
{
short m_1;
int m_2[33];
};```

sizeof’(s3, 0) = 0

sizeof’(s3, 1) = ceil(sizeof’(s3, 0) / alignof(s3.m_1)) alignof(s3.m_1) + sizeof(s3.m_1) = ceil(0 / 2) 2 + 2 = 2

sizeof’(s3, 2) = ceil(sizeof’(s3, 1) / alignof(s3.m_2)) alignof(s3.m_2) + sizeof(s3.m_2) = ceil(2 / 4) 4 + 4 * 33 = 136

maxalignof = max(alignof(s3.m_1), alignof(s3.m_2)) = max(2, 4) = 4

sizeof(s3) = ceil(sizeof’(s3, 2) / maxalignof) maxalignof = ceil(136 / 4) 4 = 136

## 3. union

```union u1
{
int m_1;
short m_2;
char m_3;
};```

sizeof(u1)的大小为多少呢?由于联合体需要共用内存,所以其大小是其成员的最大大小,再加上根据联合体对齐值进行填充的数据大小(需要填充的原因和结构体一致),而联合体的对齐值则跟结构体一样,为其成员的最大对齐值

alignof(U) = max(alignof(M1), alignof(M2), …, alignof(Mn))

sizeof(U) = ceil(max(sizeof(M1), sizeof(M2), …, sizeof(Mn)) / alignof(U)) * alignof(U)

alignof(u1) = max(alignof(u1.m_1), alignof(u1.m_2), alignof(u1.m_3)) = max(4, 2, 1) = 4

sizeof(u1) = ceil(max(sizeof(u1.m_1), sizeof(u1.m_2), sizeof(u1.m_3)) / alignof(u1))alignof(u1) = ceil(max(4, 2, 1) / 4) 4 = 4

```struct s1
{
int m_1;
short m_2;
int m_3;
short m_4;
};

union u1
{
int m_1;
char m_2[33];
s1 m_3[2];
};```

alignof(u1) = max(alignof(u1.m_1), alignof(u1.m_2), alignof(u1.m_3)) = max(4, 1, 4) = 4

sizeof(u1) = ceil(max(sizeof(u1.m_1), sizeof(u1.m_2), sizeof(u1.m_3)) / alignof(u1))alignof(u1) = ceil(max(4, 1 33, 16 2) / 4) 4 = 36

## 4. bit field(位域)

```struct s4
{
int m_1 : 16;
int m_2 : 8;
int m_3 : 8;
short m_4 : 4;
};```

## 5. alignas 和 alignof

c++11引入了对齐相关的 alignas 说明符和 alignof 运算符,其中alignof的作用其实和我们之前自己定义的alignof函数相似,用以获取类型的对齐值,而alignas则提供了一种让我们自行设置类型对齐值的方法.

```struct alignas(8) s5
{
char m_1;
alignas(1) int m_2;
char m_3;
alignas(4) short m_4;
};```

alignof(S) = max(alignof(M1), alignof(M2), …, alignof(Mn))

alignof(S) = max(alignas, alignof(M1), alignof(M2), …, alignof(Mn))

sizeof’(s5, 0) = 0

sizeof’(s5, 1) = ceil(sizeof’(s5, 0) / alignof(s5.m_1)) alignof(s5.m_1) + sizeof(s5.m_1) = ceil(0 / 1) 1 + 1 = 1

sizeof’(s5, 2) = ceil(sizeof’(s5, 1) / alignof(s5.m_2)) alignof(s5.m_2) + sizeof(s5.m_2) = ceil(1 / 4) 4 + 4 = 8 (alignof(s5.m_2) = max(1, 4))

sizeof’(s5, 3) = ceil(sizeof’(s5, 2) / alignof(s3.m_3)) alignof(s3.m_3) + sizeof(s3.m_3) = ceil(8 / 1) 1 + 1 = 9

sizeof’(s5, 4) = ceil(sizeof’(s5, 3) / alignof(s3.m_4)) alignof(s3.m_4) + sizeof(s3.m_4) = ceil(9 / 4) 4 + 2 = 14 (alignof(s5.m_4) = max(4, 2))

maxalignof = max(8, alignof(s5.m_1), alignof(s5.m_2), alignof(s5.m_3), alignof(s5.m_4)) = max(8, 1, 4, 1, 4) = 8

sizeof(s5) = ceil(sizeof’(s5, 4) / maxalignof) maxalignof = ceil(14 / 8) 8 = 16

s5的内存布局如下:

## 6. pragma pack etc. ?

```#pragma pack(1)
struct s6
{
int m_1;
short m_2;
};
#pragma pack()```

alignof(s6.m_1) = min(1, 4) = 1

alignof(s6.m_2) = min(1, 2) = 1

alignof(s6) = min(1, alignof(s6.m_1), alignof(s6.m_2)) = 1

## 7. virtual method table (vtable)

C++为了实现多态使用了虚拟函数表,每一个包含至少一个虚函数的类型都会有一张虚函数表,每一个对应类型的实例都存有一个虚函数表指针指向该类型的虚函数表,一般来讲虚函数表指针都放在类型实例内存布局的首部.

```struct cv1
{
int m_1;
virtual ~cv1() {};
};```

sizeof’(cv1, 0) = 0

sizeof’(cv1, 1) = ceil(sizeof’(cv1, 0) / alignof(cv1.vptr)) alignof(cv1.vptr) + sizeof(cv1.vptr) = ceil(0 / 4) 4 + 4 = 4

sizeof’(cv1, 2) = ceil(sizeof’(cv1, 1) / alignof(cv1.m_1)) alignof(cv1.m_1) + sizeof(cv1.m_1) = ceil(4 / 4) 4 + 4 = 8

maxalignof = max(alignof(cv1.vptr), alignof(cv1.m_1)) = max(4, 4) = 4

sizeof(cv1) = ceil(sizeof’(cv1, 2) / maxalignof) maxalignof = ceil(8 / 4) 4 = 8

cv1的内存布局如下:

137 篇文章103 人订阅

0 条评论

## 相关文章

### POJ1258:Agri-Net-最小生成树

Farmer John has been elected mayor of his town! One of his campaign promises was...

862

1643

47615

### Numpy教程第1部分 - 阵列简介（常用基础操作总结）

【导读】这里是numpy教程的基础部分，涵盖了使用numpy的ndarrays执行数据操作和分析的一些操作。众所周知，Numpy是Python中最基本和最强大的...

2754

### 搜索（6）

题目大意是在一个nxn的方阵地图上，每一个方格都标记+号或者-号,要从A点到B点。题目要求移动路线要+-交替，问怎么移动从A到B才是最短路径？  同样...

1203

811

842

### 1116 四色问题

1116 四色问题  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解 题目描述 Description 给定N（小于...

2775

2189

3424