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预课06 基于百度大脑AI的人工智能,百度颜值检测,语音合成与识别
百度大脑: 如下图,百度开放了许多人工智能接口可以使用,先注册一个百度大脑账户 点击创建应用,选择需要的功能,如人脸识别,语音识别等 点击查看文档,可以查看功能对应语言的方法,参数.首先在CMD命令下 ...
- CSS进阶之路
下面主要引用http://www.cnblogs.com/wangfupeng1988/tag/css知多少/ CSS进阶笔记: 一.学习CSS的三个突破点 1.浏览器如何加载和解析CSS——CSS的 ...
- SpringBoot配置ThreadPoolTaskExecutor
package com.example.demo; import org.springframework.context.annotation.Bean; import org.springframe ...
- 【HTTP】另类的POST头数据 RFC1867协议格式简析
http://blog.csdn.net/ai2000ai/article/details/52161979 昨天在实战表单模拟提交的时候,有发现在提交某个表单的时候,页面(discuz!论坛)报错, ...
- JAVA基础--MySQL(二)
数据库约束 1.基础限制 ① 单一表内字节量总和不能超过65535,null 占用一个字节空间 ② varchar存储255 以内字节占用一个字节表示长度,255以上自己则占用两个字节表示长度 ③ ...
- 为arm-linux开发板挂载基于nfs的根文件系统
linux4.14内核,首先设置kernel的bootargs,在make menuconfig中有三种方式来配置: 第一种方式为如果uboot中设置了bootargs环境变量,就采用uboot的bo ...
- mac 搭建Java Spring boot 环境(idea)
首先安装插件 安装下面的这个插件 然后重启idea,新建工程 选择新建 Springboot 框架 改写项目名称 选择类型 设置工程名称 删除多余的文件 编译工程 然后运行 1. 2. 参考: htt ...
- python requests 保存图片
html = requests.get('https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec ...
- Nexus OSS私服仓库的备份与迁移
背景 在上一篇博客 [Maven学习]Nexus OSS私服仓库的安装和配置 中,我们已经在机房搭建好了新的Nexus OSS私服仓库.下面是两个版本的Nexus OSS私服仓库的对比图. 老的Nex ...
- An internal error occurred during: "Synchronizing"
An internal error occurred during: "Synchronizing" “同步”期间发生内部错误. 处理方法 :单个文件进行更新,将无法更新的文件进行 ...