因为结构体有时候需要字节对齐。一般而言,struct 的 sizeof 是所有成员字节对齐后长度相加,而 union 的 sizeof 是取最大的成员长度。

在默认情况下,编译器为每一个变量或数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变默认的对界条件:

(1) 使用伪指令#pragma pack(n),C编译器将按照n个字节对齐。

(2) 使用伪指令#pragma pack(),取消自定义字节对齐方式。

字节对齐的细节和编译器实现相关,但一般而言,满足以下3个准则:

(1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除。

(2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节。

(3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

需要注意的是,基本类型是指前面提到的像 char、short、int、float、double 这样的内置数据类型。如果一个结构体中包含另外一个结构体成员,那么此时最宽基本类型成员不是该结构体成员,而是取基本类型的最宽值。

1、 默认对齐方式

#include <iostream>

using namespace std;

typedef struct
{
char ch1; // 1个字节,成员的大小为1,所以不用补齐,结构体大小就是1的整数倍,为3
char ch2;
char ch3;
}A1; typedef struct
{
int num; // 5个字节,补齐为8字节
char ch;
}A2; typedef struct
{
char a; // 1字节+补齐
int b; // 8字节
long long c; // 16字节
char d; // TotalSize= 17 ,但是不是成员c的倍数,所以+7 == 24,才是8的倍数
}A3; typedef struct
{
long num; // 4字节
char * name; // 8字节
short int data; // 10字节
char ha; // 11字节+补齐,为12字节
}A4; int main(void)
{
cout << "A1: " << sizeof(A1) << endl; // A1: 3
cout << "A2: " << sizeof(A2) << endl; // A2: 8
cout << "A3: " << sizeof(A3) << endl; // A3: 24
cout << "A4: " << sizeof(A4) << endl; // A4: 12 return 0;
}

2、位域方式

#include <iostream>

using namespace std;

typedef struct
{
char ch1:1; // 1+3+3=7位,所以只占1个字节
char ch2:3;
char ch3:3;
}A1; typedef struct
{
char ch1 : 5; // 5+5+3=13位,所以只占2个字节
char ch2 : 5;
char ch3 : 3;
}A2; typedef struct
{
char ch1 : 5; // 5+5+4=14位,却占3个字节 【注意】
char ch2 : 5;
char ch3 : 4;
}A3; typedef struct
{
char ch1 : 7; // 7+7=14位,却只占2个字节 【注意】
char ch2 : 7;
}A4; typedef struct
{
char ch1 : 1; // 偏移1个字节
int a : 16; // 偏移5个字节
int b : 16; // 偏移5个字节,因为16+16<=32,未超出“int”,所以只补齐为8个字节
}A5; typedef struct
{
char ch1 : 1; // 偏移1个字节
int a : 16; // 偏移5个字节
int b : 17; // 偏移5个字节,因为16+17>33,超出“int”,所以补齐为12个字节
}A6; int main(void)
{
cout << "A1: " << sizeof(A1) << endl; // A1: 1
cout << "A2: " << sizeof(A2) << endl; // A2: 2
cout << "A3: " << sizeof(A3) << endl; // A3: 3
cout << "A4: " << sizeof(A4) << endl; // A4: 2
cout << "A5: " << sizeof(A5) << endl; // A5: 8
cout << "A6: " << sizeof(A6) << endl; // A6: 12 return 0;
}

3、使用#pragma pack(n)

#include <iostream>
using namespace std; #pragma pack(1) // 要求补齐为“1”的倍数
typedef struct
{
char ch1; // 1+0 字节,由于自定义了对齐方式,所以不再补齐
int b; // 5 字节
int a; // 9 字节
}A1; #pragma pack(2) // 要求补齐为“2”的倍数
typedef struct
{
char ch1; // 1+1 字节,由于自定义了对齐方式,补齐为"2"的倍数
int b; // 6 字节
int a; // 10 字节
}A2; #pragma pack(4) // 要求补齐为“4”的倍数
typedef struct
{
char ch1; // 1+3 字节,由于自定义了对齐方式,补齐为"4"的倍数
int b; // 8 字节
int a; // 12 字节
}A3; int main(void)
{
cout << "A1: " << sizeof(A1) << endl; // A1: 9
cout << "A2: " << sizeof(A2) << endl; // A2: 10
cout << "A3: " << sizeof(A3) << endl; // A3: 12 return 0;
}

注意当 #pragma pack 的 n 值等于或超过所有数据成员长度的时候,这个 n 值的大小将不产生任何效果。

4、结构体中有结构体成员

#include "stdafx.h"
#include <iostream> using namespace std; typedef struct
{
short i; // 2字节 char c; // 3字节,由于后一个数据为int类型,故补齐为4字节
int j; // 8字节 int k; // 12字节
}A1; /*
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?只需把其展开即可。
但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
结构体stu5的成员ss.c的偏移量应该是4,而不是2。
*/
typedef struct
{
short i; // 2+2字节 (因为展开后的结构体的第一个成员的偏移量为4) struct
{
char c; // 5字节,补齐为8
int j; // 12字节
}A; int k; // 16字节 }A2; int main(void)
{
cout << "A1: " << sizeof(A1) << endl; // A1: 12
cout << "A2: " << sizeof(A2) << endl; // A2: 16 return 0;
}

C++中的结构体所占内存空间总结的更多相关文章

  1. C/C++ 结构体成员在内存中的对齐规则(转载)

    这几天在看王艳平的<windows 程序设计>,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因 ...

  2. C/C++ 结构体成员在内存中的对齐规则

    这几天在看王艳平的<windows 程序设计>,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因 ...

  3. C语言中处理结构体的原理

    汇编中有几种寻址方式,分别是直接寻址:(ds:[idata]).寄存器间接寻址(ds:[bx]).寄存器相对寻址(ds:[bx + idata].ds:[bx + si])基址变址寻址(ds:[bx ...

  4. x264中重要结构体参数解释,参数设置,函数说明 <转>

    x264中重要结构体参数解释http://www.usr.cc/thread-51995-1-3.htmlx264参数设置http://www.usr.cc/thread-51996-1-3.html ...

  5. C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】

    引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...

  6. C/C++中的结构体

    结构体定义 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构.   结构体作用 结构体和其他类型基础数据类型一样,例如int类型,char类型 只不过结构体可以做成 ...

  7. C语言中的结构体,结构体数组

    C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...

  8. 再识C中的结构体

    在前面认识C中的结构体中我介绍了结构体的基础知识,下面通过这段代码来回顾一下: #include<stdio.h> #define LEN 20 struct Student{ //定义结 ...

  9. 关于C语言中结构体中的结构体成员导致的字节对齐问题

    关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...

随机推荐

  1. Gamification vs. Game-Based Learning

    http://www.immersedgames.com/gamification-vs-game-based-learning/ With the growth in popularity of v ...

  2. c++、oc、swift初步评价

    c++是面向对象的多态语言: oc是面向对象的动态语言: swift是面向对象.面向协议.高阶类型.函数式编程语言:

  3. service里无法注入mapper,mapper空指针

    被困扰了一天,终于解决了,记录一下 下面是mapper的代码 @Mapper public interface ProductDao { @Select("select * from pro ...

  4. Substrings SPOJ - NSUBSTR (后缀自动机)

    Substrings \[ Time Limit: 100ms\quad Memory Limit: 1572864 kB \] 题意 给出一个长度为 \(250000\) 的字符串,求出所有 \(x ...

  5. loj2058 「TJOI / HEOI2016」求和 NTT

    loj2058 「TJOI / HEOI2016」求和 NTT 链接 loj 思路 \[S(i,j)=\frac{1}{j!}\sum\limits_{k=0}^{j}(-1)^{k}C_{j}^{k ...

  6. Cogs 513. 八(容斥原理)

    八 ★☆ 输入文件:eight.in 输出文件:eight.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] 八是个很有趣的数字啊.八=发,八八=爸爸,88=拜拜.当然最有趣的 ...

  7. 洛谷P4735题解

    若想要深入学习可持久化0-1Trie树,传送门. Description: 给定数列 \(\{a_n\}\) ,支持两种操作: 在数列尾添加一个数 \(x\) ,数列长度变成 \(n+1\) ; 给定 ...

  8. Xilinx ISE中Synplicity.ucf无法加上去的问题

    在Xilinx ISE中使用Synplify pro进行综合时,有时出现无法将synplicity.ucf添加进工程的问题.这时可以在其它目录下备份synplicity.ucf, 然后使用clean ...

  9. planAhead的启动时间较长

    发现Xilinx planAhead的启动时间约需10秒钟.

  10. Mongoose 两个表关联查询aggregate 以及 Mongoose中获取ObjectId

    Mongoose 两个表关联查询aggregate 通常两个表关联查询的时候,是一种一对多的关系,比如订单与订单详情就是一对多的关系,一个订单下面有多个商品 数据模拟 首先我们先将数据模拟出来,先选择 ...