C++中的结构体所占内存空间总结
因为结构体有时候需要字节对齐。一般而言,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++中的结构体所占内存空间总结的更多相关文章
- C/C++ 结构体成员在内存中的对齐规则(转载)
这几天在看王艳平的<windows 程序设计>,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因 ...
- C/C++ 结构体成员在内存中的对齐规则
这几天在看王艳平的<windows 程序设计>,第5章讲解了MFC框架是怎么管理窗口句柄到窗口实例之间的映射,用到了两个类CPlex和CMapPtrToPtr,用于管理内存分配的类(避免因 ...
- C语言中处理结构体的原理
汇编中有几种寻址方式,分别是直接寻址:(ds:[idata]).寄存器间接寻址(ds:[bx]).寄存器相对寻址(ds:[bx + idata].ds:[bx + si])基址变址寻址(ds:[bx ...
- x264中重要结构体参数解释,参数设置,函数说明 <转>
x264中重要结构体参数解释http://www.usr.cc/thread-51995-1-3.htmlx264参数设置http://www.usr.cc/thread-51996-1-3.html ...
- C/C++编程笔记:C语言对齐问题【结构体、栈内存以及位域对齐】
引言 考虑下面的结构体定义: 假设这个结构体的成员在内存中是紧凑排列的,且c1的起始地址是0,则s的地址就是1,c2的地址是3,i的地址是4. 现在,我们编写一个简单的程序: 运行后输出: 为什么会这 ...
- C/C++中的结构体
结构体定义 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构. 结构体作用 结构体和其他类型基础数据类型一样,例如int类型,char类型 只不过结构体可以做成 ...
- C语言中的结构体,结构体数组
C语言中的结构体是一个小难点,下面我们详细来讲一下:至于什么是结构体,结构体为什么会产生,我就不说了,原因很简单,但是要注意到是结构体也是连续存储的,但要注意的是结构体里面类型各异,所以必然会产生内存 ...
- 再识C中的结构体
在前面认识C中的结构体中我介绍了结构体的基础知识,下面通过这段代码来回顾一下: #include<stdio.h> #define LEN 20 struct Student{ //定义结 ...
- 关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...
随机推荐
- Python 类的继承__init__() takes exactly 3 arguments (1 given)
类(class),可以继承基类以便形成具有自己独特属性的类,我们在面向对象的编程中,经常用到类及其继承,可以说没有什么不是类的,今天我们就来详细探讨一下在python中,类的继承是如何做的. 我们假设 ...
- 关于vue+axios上传文件的踩坑分析
上传文件是每个前端开发者都会遇到的问题,在之前实习期做了一个上传文件的功能,当时没有彻底搞明白问题所在,现在重新复盘下. 1.使用formData来上传文件,没有使用axios上传文件,之前在学校有做 ...
- iOS开源库分类
语言库 rx aop kvo 功能库 UI network data-model-map cache 跨平台库 wkjscorebridge jspatch 性能监控库:友盟 部署库:jspathc ...
- For 32-bit BOOL is a signed char, whereas under 64-bit it is a bool.
https://stackoverflow.com/questions/31267325/bool-with-64-bit-on-ios/31270249#31270249 Definition of ...
- VSCode 如何操作用户自定义代码片段
自己写了一些根据自己习惯弄成的自定义代码片段,不喜跳过 很简单,快速过一下,F1,然后输入 snippets vue代码片段 { // Place your snippets for vue here ...
- CentOS7 配置阿里云yum源,vim编辑器,tab自动补全
1.进入yum的文件夹 命令:cd /etc/yum.repos.d/ 2.下载wget 命令:yum -y install wget 3.删除yum文件夹所有yum源 命令:rm -rf ...
- Traefik 2.0 发布了
Traefik 2.0 发布了,包含了很多不错的行特性 tcp 路由(同时也支持sni 路由) 参考配置 tcp: routers: to-db-1: entrypoints: - web-secur ...
- [RN] React Native 分享弹窗 ShareAlertDialog
React Native 分享弹窗 ShareAlertDialog ShareAlertDialog.js文件 /** * 分享弹窗 */ import React, {Component} fro ...
- yum 安装,可以list,但是无法安装Error downloading packages: 。。。。 No such file or directory
yum 安装,可以list,但是无法安装Error downloading packages: .... No such file or directory # yum install nano Lo ...
- nginx架构分析之 架构
Nginx服务器使用 master/worker 多进程模式. 主进程(Master process)启动后,会接收和处理外部信号: 主进程启动后通过fork() 函数产生一个或多个子进程(work ...