转1个写的比较全面的.

http://hubingforever.blog.163.com/blog/static/17104057920122256134681/

本文编辑整理自:
http://hi.baidu.com/pine515/blog/item/28f41f496042e8ee83025c4e.html
http://blog.sina.com.cn/s/blog_4913c1f301000bip.html
一、 ANSI C标准中并没有规定,相邻声明的变量在内存中一定要相邻。
,,。而且在上述的三条中,第2条里,offset必须是成员 大小的整数倍,如果这个成员大小小于等于4则按照上述准则进行,但是如果大于4了,则结构体每个成员相对于结构体首地址的偏移量(offset)只能按照 是4的整数倍来进行判断是否添加填充。
譬如:
) ) ,如果这个值比结构体成员的sizeof值小,那么该成员的偏移量应该以此值为准,即是说,结构体成员的偏移量应该取二者的最小值,公式如下:
offsetof( item ) = min( n, sizeof( item ) )
注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。
   VC对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。
VC 中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏 移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条 件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。
下面举例说明其用法。
#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。
四、“空结构体”(不含数据成员)的大小不为0,而是1。
试想一个“不占空间”的变量如何被取地址、两个不同的“空结构体”变量又如何得以区分呢?于是,“空结构体”变量也得被存储,这样编译器也就只能为其分配一个字节的空间用于占位了。
如下:
struct S { };
sizeof( S ); // 结果为1

经过我验证,在VC2008上的确如此。
五、含位域结构体的sizeof
位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在
六、一些面试题
 Intel、微软等公司曾经出过一道类似的面试题:
1. #include <iostream.h>
2. #pragma pack(8)
3. struct example1
4. {
5. short a;
6. long b;
7. };
8. struct example2
9. {
10. char c;
11. example1 struct1;
12. short e;    
13. };
14. #pragma pack()
 
15. int main(int argc, char* argv[])
16. {
17. example2 struct2;
18. cout << sizeof(example1) << endl;
19. cout << sizeof(example2) << endl;
20. cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) 
<< endl;
21. return 0;
22. }
问程序的输入结果是什么?答案是:
  程序中第2行#pragma pack (8)虽然指定了对界为8,但是由于struct example1中的成员最大size为4(long变量size为4),故struct example1仍然按4字节对界,struct example1的size为8,即第18行的输出结果;
  struct example2中包含了struct example1,其本身包含的简单数据成员的最大size为2(short变量e),但是因为其包含了struct example1,而struct example1中的最大成员size为4,struct example2也应以4对界,#pragma pack (8)中指定的对界对struct ex
ample2也不起作用,故19行的输出结果为16;
  由于struct example2中的成员以4为单位对界,故其char变量c后应补充3个空,其后才是成员struct1的内存空间,20行的输出结果为4。

七天、补充
有朋友对上面的内容提出了一下质疑:
质疑1
2012-01-03 01:08 | 回复

我 在自己的机子上测试了一下,发现linux上用 gcc(4.6.1)编译后struct的内存对齐和vs2010里的cl.exe一样,都是以最大成员长度为准,不像文章所说的gcc里最大是4个字 节。另外在linux上可以定义空struct,用sizeof获取长度为0,这也和文章所说的不一致,我在vs2010里没法定义空struct,所以 没有得到结果。 
  
个人觉得可能是新版本的编译器已经把这部分的规则统一了。

内存对齐-C语言struct内存占用问题的更多相关文章

  1. 什么是内存对齐,go中内存对齐分析

    内存对齐 什么是内存对齐 为什么需要内存对齐 减少次数 保障原子性 对齐系数 对齐规则 总结 参考 内存对齐 什么是内存对齐 弄明白什么是内存对齐的时候,先来看一个demo type s struct ...

  2. JVM内存管理------JAVA语言的内存管理概述

    引言 内存管理一直是JAVA语言自豪与骄傲的资本,它让JAVA程序员基本上可以彻底忽略与内存管理相关的细节,只专注于业务逻辑.不过世界上不存在十全十美的好事,在带来了便利的同时,也因此引入了很多令人抓 ...

  3. Net的struct的内存对齐问题

    很少有人谈起struct的内存对齐问题, 就是在很多C#书中, 也很少提及. 但在实际应用中, 如果不注意内存对齐, struct比较大的话, 则会浪费一定的内存.    先从一个实例看起. publ ...

  4. C语言内存对齐

    转:http://blog.csdn.net/embeddedman/article/details/7429976 首先由一个程序引入话题:  1 //环境:vc6 + windows sp2 2  ...

  5. 从硬件到语言,详解C++的内存对齐(memory alignment)

    转载请保留以下声明 作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则 ...

  6. 从硬件到语言,详解C++的内存对齐(memory alignment)(一)

    作者:赵宗晟 出处:https://www.cnblogs.com/zhao-zongsheng/p/9099603.html 很多写C/C++的人都知道“内存对齐”的概念以及规则,但不一定对他有很深 ...

  7. C\C++ 内存对齐现象

    前几天一个在自学C语言的小伙伴问了我个问题,C语言结构体储存所占空间为啥和自己预测的不一样.看一下下面这一段代码: struct node{ int num; char ch; }a; printf( ...

  8. C/C++中的内存对齐 C/C++中的内存对齐

    一.什么是内存对齐.为什么需要内存对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址 ...

  9. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

随机推荐

  1. C语言 猜数游戏--产生一个随机数

    #include <stdio.h> #include <time.h> #include <stdlib.h> int main(int argc, const ...

  2. ★Linux磁盘配额的使用 ★——牛刀小试

    磁盘配额的作用:限制普通用户使用磁盘的空间和创建文件的个数,不至于因为个别人的浪费而影响所有人的使用 需要用户程序quota软件包 #rpm -qa | grep quota  查看quota软件包安 ...

  3. 身处IT的你对身边人都有哪些影响

    前不久,跟外甥一起吃饭:他明年就要中考了,我就想,这马上就到人生的关键路口了,看他自己对将来有什么想法没:就问了句:勇勇,你以后想学习哪些方面的东西或者想从事什么工作呢?他简单的说了句:我要跟你一样学 ...

  4. 前端工程搭建NodeJs+gulp+bower

    需要node.npm的事先安装!! 1.nodejs安装程序会在环境变量中添加两个变量: 系统环境变量中:path 增加C:\Program Files\nodejs\ 因为在该目下存在node.ex ...

  5. sql server 查询多个不关联表且对结果编号

    1.除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图.内联函数.派生表.子查询和公用表表达式中无效. 解决方法:top 100 percent * 2.如何对查询结果编 ...

  6. Ajax入门小例子

    大牛文章:http://www.cnblogs.com/guduoduo/p/3681296.html                               ---Ajax基础学习 http:/ ...

  7. Oracle 动态视图3 V$SESSION

    每一个连接到数据库实例中的session都拥有一条记录.包括用户session及后台进程如DBWR,LGWR,arcchiver等 Column Datatype Description SADDR ...

  8. VS2010配色方案

    http://studiostyl.es/ 导入步骤:  工具------------导入和导出设置------------导入选定的环境设置------------否,仅导入新设置--------- ...

  9. require.js入门指南(三)

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  10. [转]system函数返回值探究

    对于system这个函数的功能早就有一定了解,读书期间,就学习了UNIX系统编程这本书,后来买了APUE.我这个人总是有好读书不求甚解的毛病.对于system函数只知其一,不知其二.后来被人问起相关的 ...