struct与union字节大小的终极解释
1、字节对齐的细节和编译器实现相关,但一般而言,如在windows下,就VC而言,满足一下三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
即:在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量:sizeof(类型)或其倍数
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节(trailing padding)
即:最大sizeof(类型)的整数倍
类型
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
Char 偏移量必须为sizeof(char)即1的倍数
int 偏移量必须为sizeof(int)即4的倍数
float 偏移量必须为sizeof(float)即4的倍数
double 偏移量必须为sizeof(double)即8的倍数
Short 偏移量必须为sizeof(short)即2的倍数
简单说明:
struct DoNothing
{
};
这个sizeof(DoNothing)肯定是1的,原因是一个“没有空间”的变量如何去取它的地址呢?如果有两个不同的空struct如何去区分它们呢?这样编译器就只好这么处理了。
struct MyStruct
{
char dda; //偏移量为0,满足对齐方式,dda占用1个字节;
double dda1; //下一个可用的地址的偏移量为1,不是sizeof(double)=8的倍数,需要补足7个字节才能使偏移量变为8(满足对齐方式),因此VC自动填充7个字节,dda1存放在偏移量为8的地址上,它占用8个节。
int type; //下一个可用的地址的偏移量为16,是sizeof(int)=4的倍数,满足int的对齐方式,所以不需要VC自动填充,type存/放在偏移量为16的地址上,它占用4个字节。
};//所有成员变量都分配了空间,空间总的大小为1 7 8 4=20,不是结构的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof 字串2(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为sizeof(double)=8的倍数。
所以该结构总的大小为:sizeof(MyStruc)为1 7 8 4 4=24。其中总的有7 4=11个字节是VC自动填充的,没有放任何有意义的东西。
2、如何修改编译器的默认对齐值?
1.在VC IDE中,可以这样修改:[Project]|[Settings],c/c++选项卡Category的Code Generation选项的Struct Member Alignment中修改,默认是8字节。
2.在编码时,可以这样动态修改:#pragma pack .注意:是pragma而不是progma.
1) n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏 移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
2) 结构的总大小也有个约束条 件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数,否则是n的倍数。
总结,struct的大小通过以下两点即可得出:
1.数据成员对齐规则:
n字节对齐就是说变量存放的起始地址的偏移量:min(sizeof(类型),对齐方式)或其倍数.
2.整体对齐规则:
结构的总大小也有个约束条件:min(最大的sizeof(类型),对齐方式)的倍数.
下面举例说明其用法。
#pragma pack(push) //保存对齐状态
#pragma pack(4)//设定为4字节对齐
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢复对齐状态
以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为 m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接 着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如 果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。
3、Union
union的长度取决于其中的长度最大的那个成员变量的长度。即union中成员变量是重叠摆放的,其开始地址相同。
其实union(共用体)的各个成员是以同一个地址开始存放的,每一个时刻只可以存储一个成员,这样就要求它在分配内存单元时候要满足两点:
1.一般而言,共用体类型实际占用存储空间为其最长的成员所占的存储空间;
2.若是该最长的存储空间对其他成员的元类型(如果是数组,取其类型的数据长度,例int a[5]为4)不满足整除关系,该最大空间自动延伸;
我们来看看这段代码:
union mm{
char a;//元长度1
int b[5];//元长度4
double c;//元长度8
int d[3]; //元长度4
};
本来mm的空间应该是sizeof(int)*5=20;但是如果只是20个单元的话,那可以存几个double型(8位)呢?两个半?当然不可以,所以mm的空间延伸为既要大于20,又要满足其他成员所需空间的整数倍,,因为含有double元长度8,故大小为24。
所以union的存储空间先看它的成员中哪个占的空间最大,拿他与其他成员的元长度比较,如果可以整除就行。
thx for:
http://www.cnblogs.com/alexkk2011/archive/2011/03/30/2000057.html
http://hi.baidu.com/gaomanyi/blog/item/9cf279638b96cb660d33fad0.html
http://blog.csdn.net/vincent_1011/article/details/4479965
struct与union字节大小的终极解释的更多相关文章
- Windows下struct和union字节对齐设置以及大小的确定(一 简介和结构体大小的确定)
在windows下设置字节对齐大小的方式,目前我了解有三种: 1. 在编译程序时候的编译选项 /Zp[n],如 cl /Zp4 表示对齐大小是4字节: 2. 预处理命令 #pragma pack ...
- 关于C中struct和union长度的详解
这几天看<代码大全>中的第十三章---不常见的数据类型,里面讲解到了C语言中的struct以及对指针的解释,联想到以前看过相关的关于C语言中stuct长度的文章,只是现在有些淡忘了,因此今 ...
- 【转】C/C++ struct/class/union内存对齐
原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...
- 关于 typedef & typedef struct & typedef union理解 --写给不长脑子的我
来源: http://zhidao.baidu.com/link?url=qxzkx5gaoCfnHnygYdzaLEWkC45JqNYYUk42eHHjB0yB3ZMgHv6lGjnq3CRfgQw ...
- 联合体union和大小端(big-endian、little-endian)
1.联合体union的基本特性——和struct的同与不同 union,中文名“联合体.共用体”,在某种程度上类似结构体struct的一种数据结构,共用体(union)和结构体(struct)同样可以 ...
- 【转】结构struct 联合Union和枚举Enum的细节讨论
结构struct 联合Union和枚举Enum的细节讨论 联合(Union)是一种构造数据类型,它提供了一种使不同类型数据类型成员之间共享存储空间的方法,同时可以实现不同类型数据成员之间的自动类型转换 ...
- C语言进阶——struct和union分析10
struct的小秘密: C语言中的struct可以看作变量的集合 struct的问题:空结构体占用多大内存呢? 程序实例1: #include <stdio.h> struct TS { ...
- <转> Struct 和 Union区别 以及 对内存对齐方式的说明
转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...
- struct与 union的基本用法
结构体与联合体是C语言的常见数据类型,可对C的基本数据类型进行组合使之能表示复杂的数据结构,意义深远,是优异代码的必备工具.一. struct与 union的基本用法,在语法上union ...
随机推荐
- Android NDK 初探,生成so文件以及调用so文件方法
因为最近业务上涉及安全的问题 然后有一些加密解密的方法和key的存储问题 本来想存储到手机里面,但是网上说一般敏感信息不要存储到手机Sdcard上 而且我这个如果从网络建立通信获取的话,又太耗时,所以 ...
- selenium ide脚本回放出现element not found
原因: 点击按钮,没有设置时间延迟,而页面加载,需要时间:当页面元素未加载完全,执行点击事件,就会报错:element... not found. 解决方案: 在点击事件前添加新的COMMAND.设置 ...
- Centos screen远程会话管理命令
screen参数 -A 将所有的视窗都调整为目前终端机的大小. -d<作业名称> 将指定的screen作业离线. -h<行数> 指定视窗的缓冲区行数. -m 即使目前已在作业中 ...
- JavaScript toLocaleString() 方法
JavaScript toLocaleString() 方法 JavaScript Array 对象 定义和用法 把数组转换为本地字符串. 语法 arrayObject.toLocaleString( ...
- JS学习笔记--仿手机发送内容交互
学习JS笔记----记录上课中学习的知识点,分享下老师教的内容: 1.html内容 <div id="box"> <div id="message&qu ...
- ARM: STM32F7: hardfault caused by unaligned memory access
ARM: STM32F7: hardfault caused by unaligned memory access ARM: STM32F7: 由未对齐的内存访问引起的hardfault异常 Info ...
- 艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)
艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项 ...
- java中调用xml的方法:DocumentBuilderFactory
具体的使用方法如下: (1)得到 DOM 解析器的工厂实例 DocumentBuilderFactory domfac=DocumentBuilderFactory.newInstance(); (2 ...
- C#开发系统服务时用的定时器组件
写服务时,都需要为定时器写不少的代码,感觉很麻烦,今天把这些代码封装一下,希望能简化一下这方面的工作,把精力都集中在功能上 本定时器组件,每次只启动一个服务实例进行处理,而不会同时多次执行服务代码. ...
- 用java实现简易PC版2048
import java.awt.Color; import java.awt.EventQueue; import java.awt.BorderLayout; import java.awt.Flo ...