因为结构体有时候需要字节对齐。一般而言,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. Spring cloud stream【消息分组】

      上篇文章我们简单的介绍了stream的使用,发现使用还是蛮方便的,但是在上个案例中,如果有多个消息接收者,那么消息生产者发送的消息会被多个消费者都接收到,这种情况在某些实际场景下是有很大问题的,比 ...

  2. WGS84与CGCS2000坐标系

    1.WGS84,WGS是世界大地测量系统World Geodetic System的缩写,84是说此坐标系是1984年建立的:   2.自上世纪60年代,美国军方相继推出WGS60.WGS66.WGS ...

  3. 简单双向链表的实现&新约瑟夫问题

    题目描述: 给定m个人,从s开始报数,数字顺加,报到n的人出列,然后数字顺减报到k的人出列,求出列顺序 样例输入: 8 1 3 2 样例输出: 3 6 1 5 2 8 4 7 分析: 约瑟夫问题主要就 ...

  4. Word pair Hu

    Memorize words in the way of games, learn foreign languages, and be more handy

  5. 临时加一条关于bootstrap的菜单栏方面的

    **有些生疏,记住了**aria-expanded表示展开状态.默认为undefined, 表示当前展开状态未知.其它可选值:true表示元素是展开的:false表示元素不是展开的. aria-hid ...

  6. Python3.x保留字(33个)

  7. [RN] React Native 解决 使用 阿里巴巴 矢量图标库 iconfont 图标不垂直居中问题

    React Native 解决 使用 阿里巴巴 矢量图标库 iconfont 图标不垂直居中问题 解决方法: 添加 size,  line-height ,值为和 height 一样的高度. 例如: ...

  8. SpringCache

    官方文档:https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/htmlsingle/#cache ...

  9. Http、Socket、WebSocket之间联系与区别

    WebSocket和Socket区别 可以把WebSocket想象成HTTP(应用层),HTTP和Socket什么关系,WebSocket和Socket就是什么关系. HTTP 协议有一个缺陷:通信只 ...

  10. JavaScript初探系列(六)——函数

    一.概述 (一)函数的声明 JavaScript 有三种声明函数的方法. (1)function 命令 function命令声明的代码区块,就是一个函数.function命令后面是函数名,函数名后面是 ...