结构体的数据对齐 #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.这种计算方法称为序 ...
随机推荐
- Bugku-CTF之域名解析(听说把 flag.baidu.com 解析到123.206.87.240 就能拿到flag)
Day 7 域名解析 50 听说把 flag.baidu.com 解析到123.206.87.240 就能拿到flag
- FL Studio的模式剪辑是什么?
FL Studio里的模式剪辑功能里,有一个模式菜单.模式剪辑菜单和模式选择器面板.模式可以作为模式剪辑放置在播放列表中,模式剪辑的名称显示在剪辑的标题栏中.(注意:模式注释和事件自动化可以共享相同的 ...
- 【BZOJ4031】小Z的房间
Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. ...
- HDU 4010 Query on The Trees(动态树)
题意 给定一棵 \(n\) 个节点的树,每个点有点权.完成 \(m\) 个操作,操作四两种,连接 \((x,y)\) :提 \(x\) 为根,并断 \(y\) 与它的父节点:增加路径 \((x,y)\ ...
- Learning-Python【3】:Python中的基本运算符
一.算数运算 二.比较(关系)运算 比较运算只能在同类型之间进行,其中 int 与 float 同属于数字类型 三.赋值运算 1.增量赋值 2.链式赋值 3.交叉赋值 交换两个数的值,通常要借助第三个 ...
- 使用windeployqt工具来进行Qt的打包发布
https://blog.csdn.net/sinat_36264666/article/details/73305712
- Linux系统初始配置标准化
Inux系统标准化 配置环境:4台Centos7.6版本的虚拟机,刚刚最小化安装完成,未作任何操作,分别是node1.node2.node3.node4 本文打算利用ansible工具对这四台虚拟机进 ...
- 3、zabbix配置入门
Zabbix模板 zabbix组件: zabbix-server zabbix-database zabbix-web zabbix-agent zabbix-proxy ...
- 《温故而知新》JAVA基础二
基本条件语句 switch语句,case匹配后会执行匹配的代码,如果没有break语句,会继续执行后面的语句,直到遇到break和程序结束为止 2.while循环 1. whie(){ do some ...
- 理解SSL、HTTPS原理中的对称加密与非对称加密
1.对称性加密 双方使用的同一个密钥,既可以加密又可以解密,这种加密方法称为对称加密,也称为单密钥加密. 简单来说就是:加密与解密都是同一个秘钥. 优点:通常在消息发送方需要加密大量数据时使用,算 ...