结构体的数据对齐 #pragma浅谈
之前若是有人拿个结构体或者联合体问我这个结构占用了多少字节的内存,我一定觉得这个人有点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浅谈的更多相关文章
- C结构体中数据的内存对齐问题
转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...
- C语言结构体的字节对齐原则
为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...
- C语言结构体的内存对齐问题
在C语言开发当中会遇到这样的情况: #include <stdio.h> struct test { int a; char b; }; int main(int argc, const ...
- C语言 结构体的内存对齐问题与位域
http://blog.csdn.net/xing_hao/article/details/6678048 一.内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地 ...
- [转]C++结构体|类 内存对齐详解
内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...
- 关于结构体占用空间大小总结(#pragma pack的使用)
关于C/C++中结构体变量占用内存大小的问题,之前一直以为把这个问题搞清楚了,今天看到一道题,发现之前的想法完全是错误的.这道题是这样的: 在32位机器上,下面的代码中 class A { publi ...
- C语言结构体变量字节对齐问题总结
结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但 ...
- 【C/C++】【VS开发】结构体存储空间数据对齐说明
关于内存对齐 一: 1.什么是内存对齐 假设我们同时声明两个变量: char a; short b; 用&(取地址符号)观察变量a, b的地址的话,我们会发现(以16位CPU为例): 如果a的 ...
- 使用qsort对结构体的数据排序
1007 DNA 排序 题目大意: 序列“未排序程度”的一个计算方式是元素乱序的元素对个数.例如:在单词序列“DAABEC'”中,因为D大于右边四个单词,E大于C,所以计算结果为5.这种计算方法称为序 ...
随机推荐
- UI自动化(五)dom
获取标签 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // 直接获取标签 document.getEleme ...
- 继上篇后的Excel批量数据导入
上篇Excel动态生成模板,此篇将借用此模板进行Excel数据的批量导入. 说明:由于数据库中部分数据储存的是编码或者Id,因此,这里就需要用到上篇中的全局数据,判断是否有数据,有数据直接使用,没有数 ...
- 【Python游戏编程01--初步认识pygame】
一.pygame简介 Pygame 是一组用来开发游戏软件的 Python 程序模块,基于 SDL 库的基础上开发.允许你在 Python 程序中创建功能丰富的游戏和多媒体程序,Pygame 是一个高 ...
- linux基础之用户和组管理及权限
一.用户和组管理 相关配置文件 /etc/passwd: 用户名 : 密码占位符 : UID : GID : COMMENTS : 家目录 :默认shell /etc/group: 组名 : 组密码占 ...
- A4988和CNC SHIELD使用方法 步进电机
接线视频 点这看视频 来源 https://www.basemu.com/a4988_pinout_and_how_to_use.html 注意要点 A4988既要12V外部供电,也要5V逻辑供电 我 ...
- SpringBoot与数据访问
pom依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...
- 使用Python访问微信
itchat是一个开源的微信个人号接口,使用它我们可以很方便的访问我们个人微信号里的信息.itchat的github地址如下: https://github.com/littlecodersh/itc ...
- opencv3.0配置opencv_contrib
在opencv3.0中无法直接使用sift,surf等特征点检测算子,需要额外配置opencv_contrib. 在查看网上诸多教程,失败n次后,终于找到了正确的配置方式. visual studio ...
- 将1~n个整数按照字典序进行排序
题意:给定一个整数n,给定一个整数k,将1~n个整数按字典顺序进行排序,返回排序后第k个元素. 题目链接:HDU6468 多组输入,T<=100,n<=1e6 分析:这个题和之前做的模拟出 ...
- Linux下更换jdk和配置环境变量
目前Linux上安装的是jdk7的java环境,由于项目原因需要升级到jdk8,无需卸载掉原本的jdk7,按如下简单步骤即可: 参考了:https://www.cnblogs.com/jiu0821/ ...