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++ 编译器内存对齐问题的更多相关文章

  1. C++内存对齐总结

    大家都知道,C++空类的内存大小为1字节,为了保证其对象拥有彼此独立的内存地址.非空类的大小与类中非静态成员变量和虚函数表的多少有关. 而值得注意的是,类中非静态成员变量的大小与编译器内存对齐的设置有 ...

  2. C/C++之内存对齐

    数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...

  3. 【C/C++开发】内存对齐(内存中的数据对齐)、大端模式及小端模式

    数据对齐,是指数据所在的内存地址必须是该数据长度的整数倍.DWORD数据的内存起始地址能被4除尽,WORD数据的内存起始地址能被2除尽.X86 CPU能直接访问对齐的数据,当它试图访问一个未对齐的数据 ...

  4. C/C++: C++位域和内存对齐问题

    1. 位域: 1. 在C中,位域可以写成这样(注:位域的数据类型一律用无符号的,纪律性). struct bitmap { unsigned a : ; unsigned b : ; unsigned ...

  5. Windows+GCC下内存对齐的常见问题

    结构/类对齐的声明方式 gcc和windows对于modifier/attribute的支持其实是差不多的.比如在gcc的例子中,内存对齐要写成: class X { //... } __attrib ...

  6. 内存对齐 和 sizeof小结

    数据对齐(内存对齐)指该数据所在的地址必须是该数据长度的整数倍.X86CPU能直接访问对齐的数据,当它试图访问未对齐的数据时,会在内部进行一系列的调整,降低运行速度.数据对齐一般出现在结构体和类中,在 ...

  7. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  8. C语言再学习之内存对齐

    昨天看Q3的代码,看到有个_INTSAIZEOF的宏,着实晕了一阵.一番google后,终于明白,这个宏的作用是求出变量占用内存空间的大小,先看看_INTSAIZEOF的定义吧: #define _I ...

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

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

随机推荐

  1. ps 快捷键

    1.前景色填充ALT+DEL 2.背景色填充CTRL+DEL 3.按D键可以以恢复默认的前景色(黑).背景色(白). 4.按X键可以切换前景色.背景色.

  2. Linux实施一次性任务

    一.定义 at命令:定时任务,指定一个时间执行一个任务,只能执行一次. 二.选项 三.示例 1. 使用 student 用户,创建一个任务,2 分钟以后执行,在/home/student/at.txt ...

  3. Data Flow ->> Term Extraction

    中文意思是关键词抽取,用于计算在文本中哪些词汇或者词组出现的频率最高.其实算法有两张:1)Frequency 2)TFIDF TFIDF的全称是Term Frequency and Inverse D ...

  4. [转载]TexturePacker 如何使用自带的加密功能及在cocos2dx中的使用

    在cocos2dx中使用纹理图集是非常节省资源的,在这里推荐 TexturePacker,而且 TexturePacker工具的加密接口也非常的好用,下面就来介绍一下... TexturePacker ...

  5. mysql 转义字符和php addslashes

    遇到一个很奇怪的问题,json数据中含有中文: "mail":{"title":"\u6218\u529b\u8fbe\u4eba\u6d3b\u52 ...

  6. 基于EntityFramework的权限的配置和验证

    1.   概要 本文主要介绍公司现有系统框架的权限体系,和一些待扩展功能的说明.目前该权限体系基于角色构建(RBAC),原则上,系统中不允许出现对用户.组织等其他对象指派权限的情况. 2.   权限分 ...

  7. Linux 添加环境变量和删除环境变量

    环境变量是一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息.例如PATH.在交叉编译中,会经常运用到环境变量的设置. 在linux中,查看当前全部的环境变量的命令式env. 当然也 ...

  8. 如何创建PostgreSQL数据库

    PostgreSQL提供两种方式创建一个新的数据库:第一种是使用CREATE DATABASE的SQL命令.第二种使用createdb的一个命令行可执行文件. 第一种:使用CREATE DATABAS ...

  9. YTU 2601: 熟悉题型——填空题(删除线性表节点)

    2601: 熟悉题型--填空题(删除线性表节点) 时间限制: 1 Sec  内存限制: 128 MB 提交: 357  解决: 212 题目描述 给出一串具体长度的数据,删除指定数据. 已经给出部分代 ...

  10. AOJ - 2224 Save your cat(最小生成树)

    http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=45524 NY在自己的花园里养了很多猫.有一天,一个巫婆在N个点设置了魔法,然 ...