C中结构体的存储分配
C中结构体的存储分配
对于C语言中结构体所占的存储空间的大小,也一直是笔试面试的常客,今天好好看了一下这方面,以前一直以为很清楚了,今天通过各种实际测试举例,发现原来还是没有搞透彻,好在现在是彻底懂了,所以和大家分享,希望能有所帮助。
提到结构体,相信大家都知道元素存储要对齐,话是没有错,只是这个“对齐”里面包含了很多微妙的东西。首先详细的给出结构体内存分配的原则吧:编译器按照成员列表顺序一个接一个地给每个成员分配内存。只有当存储成员时需要满足正确的边界对齐要求时,成员之间才可能出现用于填充的额外内存空间。接下来我们来慢慢理解这句话。
sizeof操作符能够得出一个结构的整体长度,包括因边界对齐而跳过的那些字节。所以一般都用sizeof来计算其所占存储空间。来看下面的例子:
struct test1
{
int a;
char b[];
char c;
};
计算可以得到test1占16个字节。原因是a占4个字节(32位机,int占4个字节),b和c分别占9个字节和1个字节,加起来10个字节,与a对齐,则需要12个字节,所以总共需要16个字节。这个例子就是我们最熟悉的,接下来看一下个。
struct test2
{
char b[];
int a;
char c;
};
计算可以得到test2占20个字节。比较test1和test2可以发现仅仅将a和b的位置换了一下,为什么结果会不同呢?这就是前面定义中所说的顺序的问题。int为最大字节,一开始分配9个字节,然后是a,为了对齐,这时候应该是12+4个字节,后面又来一个char,为了对齐加4,所以总共是20个字节。而test1因为后面两个类型一致,所以可以和在一起分配,然后对齐。
接下来我们在加大难度,看如下例子:
struct test3
{
char b[];
int a;
char c;
double d;
};
按照上面的逻辑,b占9个字节,a占4个字节,为了和a对齐,所以此时应该是12+,接着是c为1个字节总共为12++=,然后是d为8个字节,为了和8字节对齐,则应该为24+=32个字节,即最终结果为32个字节。变换一下顺序,得到如下例子:
struct test4
{
char b[];
int a;
double d;
char c;
};
同样的,b和a占据12+4个字节,d为8个字节,则应该是16+=,加上最后的一个字节,为了对齐,总共也是24+=32个字节。这里需要注意的是,若数组b元素改为13,则为了对齐,d前面应该是16+4,然后遇到d,对齐后为24+8,在加上最后的8个字节,应该为40个字节。
再来看一个:
struct test4
{
double d;
char b[];
int a;
char c;
};
d占8个字节,b占9个字节,后面是int,为了对齐,加上a应该是20+,再加上1个字节,为了和最大的double对齐,所以应该是20++=32个字节。
好了,通过列举这么多不同的例子,最终目标只有一个,是真的搞清楚某个结构体占据的空间大小。通过上面的例子,我总结了以下几点。
)首先,看该结构体中最大的“基元素”(这是我杜撰的,就是说基本元素类型最大的是哪个,例如test1和test2都是int,而test3和test4都是double,而不是看数组总共所占据的大小),找到这个以后,结构体所占据的空间的大小一定要是该基本元素所占空间大小的整数倍。
)接着,按顺序将元素进行排列。前一元素要与后一元素对齐,如果后一元素的“基元素”比前一个大,则前一元素需要调整大小,即对齐该后一元素。
)最后将得到的字节大小加起来,跟最大的基元素对齐,即得到最终的所占存储空间大小。
如果要确定结构中某个成员的实际位置,可以使用offsetof宏(stddef.h)offsetof(type,member)。type是结构的类型,member是该结构的成员名,表达式的结构是一个sizeof_t值。表示该指定成员的存数位置(离该结构体存储的起始位置)。
另外还有一点值得一提的是,当结构体里面包含另一结构体时,直接将该结构体中的内容代换进去,计算其总的存储空间即可。
http://blog.sina.com.cn/s/blog_67b077fe0101844k.html
C中结构体的存储分配的更多相关文章
- C#中结构体和类的区别
结构体和类同样能够定义字段,方法和构造函数,都能实例化对象,这样看来结构体和类的功能好像是一样的了,但是他们在数据的存储上是不一样的 C#结构体和类的区别问题:这两种数据类型的本质区别主要是各自指向的 ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
一个工作任务涉及到c#与c++系统间的udp通信,处理了蛮长时间没有完成任务,但是期间接触到不少小知识点.本人是初接触c#,c++语言没有接触过.可能写的东西都很小儿科,暂且记录下来当工作日记把. 先 ...
- 《挑战30天C++入门极限》C/C++中结构体(struct)知识点强化
C/C++中结构体(struct)知识点强化 在上一个教程中我们已经简单的阐述了什么是结构体了,为了进一部的学习结构体这一重要的知识点,我们今天来学习一下链表结构. 结构体可以看做是一种自定义 ...
- C语言中结构体内存存储方式
C语言中结构体内存存储方式 结构体的默认存储方式采用以最大字节元素字节数对其方式进行对齐,例如一个结构体中定义有char.int类型元素,则结构体存储空间按照int类型占用字节,如果还有double类 ...
- STM32L0系列EEPROM中结构体的读取
在STM32L0中操作EEPROM本来参考了上篇操作FLASH的方法,多多少少都有些问题.我觉得可能是结构体在转换成其他变量的时候出了问题. 比如下面这段代码,在Windows上可以正常运行(使用g+ ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- OC中结构体作为对象属性
在OC中结构体有时候也作为对象的属性 类的定义 #import <Foundation/Foundation.h> typedef struct{ int year; int month; ...
- C C++ 中结构体与类
先来说说C和C++中结构体的不同 a) C语言中的结构体不能为空,否则会报错 1>d:\myproject\visual studio 2013\projects\myc++\main.c(71 ...
随机推荐
- 【微信小程序】用户首次进入小程序拒绝授权,如何再次调用授权页面,获取用户信息userInfo
前言:微信小程序的app.js里面,最少有2个接口,一个wx.login:一个是wx.getUserInfo: 前者得到腾讯给我们的微信用户唯一的code,通过code获取openid,这个不需要用户 ...
- Zookeeper监控工具
Zookeeper的常用开源监控工具可以参考:http://zqhxuyuan.github.io/2016/12/31/BigData-Monitor-Tool
- DBA_实践指南系列8_Oracle Erp R12数据维护模式Adadmin(案例)
2013-12-08 Created By BaoXinjian
- android中ImageView的ScaleType属性
android中ImageView的ScaleType属性 ScaleType的值分别代表的意义: ImageView是Android中的基础图片显示控件,该控件有个重要的属性是ScaleType,该 ...
- vim 折叠
zR 打开全部折叠 zr 打开当前折叠 zM 关闭全部折叠 zm 关闭当前折叠
- ArcMap导入数据到ArcSDE报000597或者000224的错误
这两天碰到不同用户提出的不同的问题,可是分析之后发现导致该问题的解决办法是同一个原因. -------------------------------------------------------- ...
- python 下载.whl 文件,查看已安装软件包方法
下载地址 https://www.lfd.uci.edu/~gohlke/pythonlibs/ 另一个Python packages地址为 https://pypi.org/ 下载 ...
- 17monipdb根据IP获得区域
https://www.ipip.net/download.html https://github.com/17mon/csharp IpAndPositionHelper public class ...
- Spring MVC 的xml一些配置
1.可以自动加载注解驱动,通过注解找到对应Controller <!-- spring MVC 注解驱动 --> <mvc:annotation-driven></mvc ...
- 高度自适应的CSS
/*高度自适应*/ .com_fill_height{ height:100%; overflow:hidden; } 高度自适应的样式代码,真的就这么简单吗...