c/c++ 编译器内存对齐问题
C语言结构体对齐问题详解
转载自:http://blog.csdn.net/tiany524/article/details/6295551
测试环境32位机 WinXP:
编译器VC6(MS cl.exe ) 和 mingw32-gcc-4.5.2
1 结构体数据对齐(没有#pragma pack()宏定义)
结构体对齐可以总结为三个基本原则
①数据成员对齐规则:
结构体的数据成员中,第一个成员从offset为0的地址开始,以后每一个成员存储的起始位置为该成员大小的整数倍(在win32中int为32bit也即4字节对齐)
②结构体作为成员:
如果一个结构体1作为另一个结构体2的数据成员,则在结构体2中结构体1要从1内部成员最大的整数倍地址开始存储。
③结构体的总大小(sizeof):
为该结构体内部最大基本类型的整数倍,不足的要补齐,而不是简单的所有成员的大小总和。
举例说明
struct{
short a;
short b;
short c; }A; sizeof(A) = 6;(vc6与gcc相同)
struct{
long a;
short c; }A; sizeof(A) = 8;(vc6与gcc相同),根据原则③
它的内存分配为: a1 a2 a3 a4 , c1 c2 x x(a1为a的第一个字节,x为补齐字节,下同)
struct{
int a;
char b;
short c; }A;
sizeof(A) = 8;
A的内存分配为: a1 a2 a3 a4, b1 x c1 c2(原则1)
struct{
char a;
int b;
short c; }A1;
sizeof(A1) = 12; (vc6与gcc相同)
A1的内存分配为: a1 x x x, b1 b2 b3 b4, c1 c2 x x
下面是更复杂的情况,结构体作为成员
struct{
int a;
doubl b;
short c; }A; // sizeof(A) = 24 (vc6与gcc相同)
struct{
char a,b;
int c;
double d;
short e;
struct A h;
}B;
sizeof(B) = 48 //(vc6与gcc相同)
A的内存分布: a1 a2 a3 a4 x x x x, b1 b2 b3 b4 b5 b6 b7 b7, c1 c2 x x x x x x
B的内存分布:a1 b1 x x, c1 c2 c3 c4 , d1 d2 d3 d4 d5 d6 d7 d8, e1 e2 x x x x, A的分布
2 加入#pragma pack()宏定义)
#pragma pack(1)
上面的AB大小分别为14,30,对应于AB的内存分布,去掉x。
pack(2)时为14,30
pack(4)时为16,36
3 结构体的位域
结构体中引入位于是为了压缩存储空间。而且位于成员不能单独计算sizeof。
位域大致有5条基本规则。
① 如果相邻字段的类型相同,且位宽之和小于该类型的sizeof(), 则可以紧邻着前一个字段存储,直到不能在容纳位置;
struct{
char a:2;
char b:4;
char c:5; }A; // sizeof(A) = 2
内存分布: a1 a2 x x, b1 b2 b3 b4, c1 c2 c3 c4 c5 x x x,这里每一个代表一个bit,与上一节不同
struct{
int a:2;
int b:3;
int c:3; }A; // sizeof(A) = 4, 参照后面的原则5
②如果相邻字段的类型相同,但是位宽之和大于该类型的sizeof(), 则后面的字段将从新的存储单元开始存储,且offset为其类型大小的整数倍;
struct{
char a:6;
char b:3;
char c:3; }A; // sizeof(A) = 2
struct{
int a:20;
int b:20;
int c:3; }A; // sizeof(A) = 8, 同时参照后面的原则5
③如果相邻位域字段类型不同,各编译器的处理不同,VC6不压缩,GCC压缩。
struct{
int a:4;
char b:1;
int c:3; }A;
sizeof(A) = 12, VC6
sizeof(A) = 4, gcc, 压缩了为什么不是3? 同时参照后面的原则5
④如果位域字段之间插入非位域字段,各编译器的处理不同
struct{
int a:4;
char b;
int c:3; }A;
sizeof(A) = 12, VC6
sizeof(A) = 4, gcc, a1 a2 a3 a4 x x x x ,b1~b8, c1 c2 c3 x x x x x
struct{
char a:4;
char b;
char c:3; }A;
sizeof(A) = 3, VC6
sizeof(A) = 3, gcc,
⑤整个结构体的总大小为其最宽基本类型的整数倍。
c/c++ 编译器内存对齐问题的更多相关文章
- C++内存对齐总结
大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...
- C/C++之内存对齐
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式
数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...
- C/C++: C++位域和内存对齐问题
1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...
- Windows+GCC下内存对齐的常见问题
结构/类对齐的声明方式 gcc和windows对于modifier/attribute的支持其实是差不多的.比如在gcc的例子中,内存对齐要写成: class X { //... } __attrib ...
- 内存对齐 和 sizeof小结
数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...
- 解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- C语言再学习之内存对齐
昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...
- C结构体中数据的内存对齐问题
转自:http://www.cnblogs.com/qwcbeyond/archive/2012/05/08/2490897.html 32位机一般默认4字节对齐(32位机机器字长4字节),64位机一 ...
随机推荐
- android-exploitme(六):基础加密
这次我们看看程序在设备上存储了什么敏感信息 (server-env)sartre:AndroidLabs2 maxim$ adb shell # cd /data/data/com.securityc ...
- linux下python启动第三方程序,并控制关闭
import subprocess import os import signal p = subprocess.Popen("recordmydesktop -o /home/test/t ...
- [vim]设置vim语法高亮显示和自动缩进
1.配置文件的位置 在目录 /etc/vim下面,有个名为vimrc的文件,这是系统中公共的vim配置文件,对所有用户都有效.而在每个用户的主目录下,都可以自己建立私有的配置文件,命名为 ...
- CentOS Mysql自动备份 .txt
http://fly.b3log.org/articles/2011/10/25/1319505473928.html MySql数据库备份: 说明:我这里要把MySql数据库存放目录/var/lib ...
- ES6入门之函数的扩展
函数js原有的: 属性:arguments[].caller(调用该函数的引用,注意与callee分别开,callee指的是调用函数本身经常在递归中出现).length(形参个数).prototype ...
- javaScript初学者易错点
大家好,这是我在博客园写的第一篇博文.作为一名前端开发初学者,由于经验不足,水平有限,在做项目的过程中总会遇到这样或那样的问题,每每这时候,我都比较喜欢到博客园这里来寻求解决方案,结果也总是能找到满意 ...
- js 去空格函数与正则
如果项目没有用到jQuery等框架的话,js本身又没有这样的函数,我们不得不自己写这样的函数,下面是函数的具体实现: //供使用者调用 function trim(s){ return trimRig ...
- 深入理解Java内存模型(五)——锁
锁的释放-获取建立的happens before 关系 锁是java并发编程中最重要的同步机制.锁除了让临界区互斥执行外,还可以让释放锁的线程向获取同一个锁的线程发送消息. 下面是锁释放-获取的示例代 ...
- CF 314C Sereja and Subsequences(树状数组)
题目链接:http://codeforces.com/problemset/problem/314/C 题意:给定一个数列a.(1)写出a的不同的所有非下降子列:(2)定义某个子列的f值为数列中各个数 ...
- [Topcoder]ZigZag(dp)
题目链接:https://community.topcoder.com/stat?c=problem_statement&pm=1259&rd=4493 题意:给一串数字,求出最长的波 ...