之前若是有人拿个结构体或者联合体问我这个结构占用了多少字节的内存,我一定觉得这个人有点low, 直到某某公司的一个实习招聘模拟题的出现,让我不得不重新审视这个问题,

该问题大致如下:

typedef struct _A{
char a;
int b;
float c;
double d;
int *pa;
char* pc;
short e;
}A;
#pragma pack(pop)
int main(int argc, char *argv[])
{
printf("size = %d\n",sizeof(A));
return 0;
}

程序输出结果是()。
A size= 48
B size= 44
C size= 40
D size= 36

乍一看,这还不简单吗, 1+4+4+8+4+4+2=27个字节,这个最少的答案也是36啊!

有同学提示说数据对齐,这才注意到预编译指令#pragma pack(pop), 一百度,得到这样的答案:

作用:指定结构体、联合以及类成员的packing alignment;

语法:#pragma pack( [show] | [push | pop] [, identifier], n )

说明:

1,pack提供数据声明级别的控制,对定义不起作用;

2,调用pack时不指定参数,n将被设成默认值;

3,一 旦改变数据类型的alignment,直接效果就是占用memory的减少,但是performance会下降;

语法具体分析:

1,show:可选参数;显示当前packing aligment的字节数,以warning message的形式被显示;

2,push:可选参数;将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈;

3,pop:可选参数;从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment数值;如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略;

4,identifier:可选参数;当同push一起使用时,赋予当前被压入栈中的record一个名称;当同pop一起使用时,从internal compiler stack中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作;5,n:可选参数;指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16。

因为没有push操作,internal compiler stack为空,所以这个条预编译指定在这里其实是没有任何作用的,使用下面这条指令查看当前的packing alignment = 8, 为默认的对齐参数。

#pragma pack(show)

再来看一下数据对齐的规则,复杂数据对齐主要分为数据成员的对齐和复杂数据整体对齐,两者都可以总结为

“在自身对齐参数和指定对齐参数中,选择小的对齐”

数据成员自身对齐参数为类型占用字节的长度,而复杂数据的自身对齐参数为最大的数据成员自身对齐参数,所谓对齐N,就是使得偏移量offset满足 offset%N = 0,并且使得数据长度尽可能短,第一数据成员的偏移量为0,

因此我们可以分析

成员变量的对齐

a的偏移量为 0,占用一个字节

此时的偏移量为0+1 =1,b的自身对齐参数即其长度为4,packing alignment =8, 顾应对齐4,顾其偏移量为4,(1+3)%4=0

此时偏移量为4+4= 8 ,而c也应对齐4, 8%4 = 0 ,故其偏移量为8

此时偏移量为8+4 = 12,而d的自身长度为8, 指定对齐参数也为8,故其对齐参数为8,所以其偏移量应为12+4=16,因为16%8 = 0

此时偏移量为16+8 = 24,而pa的对齐参数为4,24%4= 0,故其偏移量为24

此时偏移量为24+4 = 28,同理pc的偏移量也为28

此时偏移量为28+4 = 32,e的对齐参数为2,32%2 =0,故其偏移量为32,长度为2,数据成员对齐后结构体A的大小为

32+2 = 34个字节

整体对齐

结构体A中,最大的成员变量的长度为8,指定的packing alignment也是8,故其应对齐8,而数据成员对齐后其大小为34, 整体对齐后其大小应为40, 因为40%8 = 0。

结构体的数据对齐 #pragma浅谈的更多相关文章

  1. C结构体中数据的内存对齐问题

    转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...

  2. C语言结构体的字节对齐原则

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

  3. C语言结构体的内存对齐问题

    在C语言开发当中会遇到这样的情况: #include <stdio.h> struct test { int a; char b; }; int main(int argc, const ...

  4. C语言 结构体的内存对齐问题与位域

    http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...

  5. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

  6. 关于结构体占用空间大小总结(#pragma pack的使用)

    关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的.这道题是这样的: 在32位机器上,下面的代码中 class A { publi ...

  7. C语言结构体变量字节对齐问题总结

    结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但 ...

  8. 【C/C++】【VS开发】结构体存储空间数据对齐说明

    关于内存对齐 一: 1.什么是内存对齐 假设我们同时声明两个变量: char a; short b; 用&(取地址符号)观察变量a, b的地址的话,我们会发现(以16位CPU为例): 如果a的 ...

  9. 使用qsort对结构体的数据排序

    1007 DNA 排序 题目大意: 序列“未排序程度”的一个计算方式是元素乱序的元素对个数.例如:在单词序列“DAABEC'”中,因为D大于右边四个单词,E大于C,所以计算结果为5.这种计算方法称为序 ...

随机推荐

  1. weex安装失败,按照官网步骤多次失败后成功

    在安装Weex Toolkit之前,需要确保安装了node, npm. yangfeifei:~ yff$ node -v v6.10.2 yangfeifei:~ yff$ npm -v 3.10. ...

  2. 采用xtrabackup部署主从同步

    1.停掉从库192.168.1.23[root@dev-env23 tmp]# service mysqld stopStopping mysqld: [ OK ] 2.主库全备份cd /opt/xt ...

  3. 8、zabbix监控方式及分布式监控(04)

    zabbix支持的监控方式 zabbix所能够显示的且可指定为监控接口类型的监控方式: Agent passive active SNMP:Simple Network Management Prot ...

  4. 6th-Python基础——集合、函数

    1.集合 主要作用: (1)去重 (2)关系测试,交集.差集difference().并集union().反向差集symmetric_difference().子集issubset().父集issup ...

  5. Git Github的区别 & Pycharm使用GitHub

    首先:git和github功能很强大,随着使用深入,我将随时填充,更新这篇文章,记录随时遇到的新的问题和感悟. 第一次知道github是看廖雪峰的课程,所谓版本管理,之前在辉煌科技用的是SVN,了解一 ...

  6. 使用scss为css样式自动添加浏览器前缀

    当一个浏览器实现一个新的属性.值或者选择器,而这个特征还不是处于候选推荐标准状态的时候,这属性的前面会添加一个前缀以便于它的渲染引擎识别. 浏览器使用前缀来尝试一些新属性.值和选择器,即使他们还没有最 ...

  7. P1325 雷达安装

    传送门 思路: 采取贪心的思想. 把每个岛屿看作圆心,以雷达的范围 d 为半径,求出与 x 轴的左右两个交点,两交点所夹的区间就需要放置一个雷达,这样就把这道题转换为了区间取点问题.在枚举岛屿时,记录 ...

  8. VC.重定向标准输出到文件(父进程方式)

    1.libxml2 使用过程中,有时 libxml2里面会报一些错误信息,在 控制台的程序中 这些信息看起来比较乱,不易观察,我想将这些信息重定向到 文件中 1.1.本进程内:试着 将标准输出,标准错 ...

  9. Hive和HBase区别

    1. 两者分别是什么? Apache Hive是一个构建在Hadoop基础设施之上的数据仓库.通过Hive可以使用HQL语言查询存放在HDFS上的数据.HQL是一种类SQL语言,这种语言最终被转化为M ...

  10. C# --- ??(空接合操作符)的一个案例

    Nullable<Int32> x = null; Nullable<Int32> y = null; Nullable<Int32> z = null; Int3 ...