本文源于微信号《嵌入式ARM》。链接:http://mp.weixin.qq.com/s/j2mk6jY79nrJge2cDZVH_A

对结构MyStruct采用sizeof会出现什么结果呢?sizeof(MyStruct)为多少呢?

也许你会这样求:sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13

但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)=16。你知道为什么在VC中会得出这样一个结果吗?

其实,这是VC对变量存储的一个特殊处理。为了提高CPU的存储速度,VC对一些变量的起始地址做了“对齐”处理。

在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。

下面列出常用类型的对齐方式(vs6.0&vs8.0,32位系统)。

各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。

下面用前面的例子来说明VC到底怎么样来存放结构的。

为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,依次分配。

(1)先为第一个成员dda1分配空间,其起始地址跟结构的起始地址相同,刚好偏移量0刚好为sizeof(double)的倍数,该成员变量占用zeof(double)=8个字节;

(2)接下来为第二个成员dda分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;

(3)接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起始地址的偏移量为12,刚好是=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;

(4)这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:

8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。

(5)所以整个结构的大小为:

sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。

下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况:

这个结构占用的空间为多大呢?在VC6.0环境下,可以得到sizeof(MyStruct)=24。结合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。

所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,不是结构的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为sizeof(double)=8的倍数。所以该结构总的大小为:sizeof(MyStruct)为1+7+8+4+4=24。其中总的有7+4=11个字节是VC自动填充的,没有放任何有意义的东西。

VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

下面举例说明其用法:

以上结构的大小为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。

在VC6中,Project SettingsàC/C++àStruct member alignment中默认值为8Bytes *。Struct member alignment用以指定数据结构中的成员变量在内存中是按几字节对齐的,根据计算机数据总线的位数,不同的对齐方式存取数据的速度不一样。这个参数对数据包网络传输等应用尤为重要,不是存取速度问题,而是数据位的精确定义问题,一般在程序中使用#pragma pack来指定。

总结之,即:
(1)可以设置不同的对齐方式,设置方式如上面所述,一般系统默认为8字节对齐。而我所知,嵌入式系统中一般默认4字节对齐?(vs2015默认4字节对齐)
(2)VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。即在结构体前后分别以#pragma pack(n),#pragma pack()进行对齐设置。
n字节对齐就是说变量存放的起始地址的偏移量有两种情况:
第一、如果n大于等于该变量类型所占用的字节数,那么偏移量必须是该类型的整数倍。
第二、如果n小于该变量的类型所所占用的字节数,那么偏移量必须是n的整数倍。
结构的总大小也有个约束条件,分下面两种情况:
如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

嵌入式C语言之struct内存分配分析相关推荐

  1. 【C语言】动态内存分配

    [C语言]动态内存分配 文章目录 [C语言]动态内存分配 一.malloc 与free函数 二.calloc 三.realloc 四.常见的动态内存的错误 本期,我们将讲解malloc.calloc. ...

  2. C/C++语言变量声明内存分配

    [cpp] view plaincopy <span style="font-family: Verdana, Arial, Helvetica, sans-serif; " ...

  3. C语言中动态内存分配的本质是什么?

    摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...

  4. c语言malloc引用类型作参数,c语言中动态内存分配malloc只在堆中分配一片内存.doc...

    c语言中动态内存分配malloc只在堆中分配一片内存 .C语言中动态内存分配(malloc)只在堆中分配一片内存,返回一个void指针(分配失败则返回0),并没有创建一个对象.使用时需要强制转换成恰当 ...

  5. 【C语言进阶深度学习记录】三十三 C语言中动态内存分配

    如何在程序运行的时候动态给程序分配内存? 文章目录 1 动态内存分配的意义 1.1 C语言中如何动态申请内存空间 1.2 malloc和free的用法 1.3 calloc与realloc 1.31 ...

  6. C语言:动态内存分配

    个人博客网址:https://ljsblog.com 动态内存分配(十) 在不知道所需要的空间大小的情况下,这时就可以使用动态内存开辟. 当开辟的空间不再使用时,用free函数来释放calloc.ma ...

  7. C语言 二级指针内存分配、初始化和释放

    二级指针的内存分配 使用malloc函数 使用calloc函数 C语言有两种内存分配函数,一个为malloc函数,一个为calloc函数.两者在使用上具有差不多的功能. 使用malloc函数 mall ...

  8. 【C语言】动态内存分配详解

    目录 一.为什么有动态内存分配 二.动态内存分配函数 (1)malloc()函数 (2)calloc()函数 (3)realloc()函数 三.常见的动态内存错误 1.越界访问 2.内存泄漏 3.对N ...

  9. 【C语言】------ 动态内存分配

    动态内存开辟详解 动态内存分配 什么是动态内存分配? 一.为什么使用动态内存分配呢? 二.动态内存函数 1.malloc和free 2.calloc和realloc 三.常见的动态内存错误 1.对`N ...

最新文章

  1. word打开时报Cannot find the Word document template:WordToRqm.dot
  2. 代码详解|tensorflow实现 聊天AI--PigPig养成记(1)
  3. 关于如何评价洗牌质量的猜想
  4. 高级指引——概念解释——图形 Shape 及其属性
  5. 射灯安装方法图解_江苏天筑不锈钢雕塑厂家格栅射灯安装方法,格栅射灯安装注意事项...
  6. mysql 无法链接, 输入密码失败
  7. java gpu hash_比特币 GPU 挖矿 Sha256 Hash实现(OpenCL)
  8. 不学网php线下培训视频教程
  9. 链表实现一元多项式的加法、乘法、求导,求值
  10. 人生的路很远,一路小心
  11. Pytorch为什么总要设置随机种子
  12. win10 IE浏览器显示无法安全下载文件
  13. viewers.js 图片查看插件使用说明-vue中引用
  14. win10 下 pdfium编译 VS2017
  15. vxlan专题---第四章配置分布式网关部署方式的华为VXLAN示例-外部路由type5
  16. python 多列排序_python sorted多列排序
  17. 让心爱的TA不再孤单——Python微信聊天机器人
  18. (46)FPGA面试技能提升篇(40GE、XGE、GE接口)
  19. DevOps是MindSet:工具也好,文化也罢,人员才是关键
  20. 以高能低碳技术融入PC全生命周期,英特尔联合业界推出绿色商用电脑

热门文章

  1. Postgres中tuple的组装与插入
  2. centos7-安装mysql5.6.36
  3. $GLOBALS -- 变量
  4. Sliverlight MD5
  5. 李洋疯狂C语言之求素数的方法
  6. 《PWA实战:面向下一代的Progressive Web APP》读书笔记
  7. LoadRunner远程监测Centos服务性能配置过程
  8. iOS开发篇——OC 协议和代理设计模式介绍
  9. iphone-common-codes-ccteam源代码 CCNSArray.h
  10. green ethernet