引用:内存字节对齐

写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧.

/******************************分割线

如果体系结构是不对齐的,A中的成员将会一个挨一个存储,从而sizeof(a)为11。显然对齐更浪费了空间。那么为什么要使用对齐呢?

体系结构的对齐和不对齐,是在时间和空间上的一个权衡。对齐节省了时间。假设一个体系结构的字长为w,那么它同时就假设了在这种体系结构上对宽度为w的数据的处理最频繁也是最重要的。它的设计也是从优先提高对w位数据操作的效率来考虑的。比如说读写时.............此处省略50万字

***********************************************************/

上面是你随便 google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则:(在没有#pragma pack宏的情况下,务必看完最后一行)

1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)

3:收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐.

4:注意套用三原则里计算的对齐值是不能大于#pragma pack指定的n值. gcc默认是#pragma pack(4),并且gcc只支持1,2,4对齐。

等你看完此3条原则,2分钟已经过去,抓紧时间,实战3分钟:

typedef struct bb

{

int id;             //[0]....[3]

double weight;      //[8].....[15]      原则1

float height;      //[16]..[19],总长要为8的整数倍,补齐[20]...[23]     原则3//注意4字节对其的编译器里面最大基数为4。

}BB;

typedef struct aa

{

char name[2];     //[0],[1]

int  id;         //[4]...[7]          原则1

double score;     //[8]....[15]

short grade;    //[16],[17]

BB b;             //[24]......[47]          原则2

}AA;

int main()

{

AA a;

cout<<sizeof(a)<<" "<<sizeof(BB)<<endl;

return 0;

}

结果是

48 24

ok,上面的全看明白了,内存对齐基本过关.

再讲讲#pragma pack().

在代码前加一句#pragma pack(1),你会很高兴的发现,上面的代码输出为

32 16

bb是4+8+4=16,aa是2+4+8+2+16=32;

这不是理想中的没有内存对齐的世界吗.没错,#pragma pack(1),告诉编译器,所有的对齐都按照1的整数倍对齐,换句话说就是没有对齐规则.

明白了不?

那#pragma pack(2)的结果又是多少呢?对不起,5分钟到了,自己去测试吧.

ps:Vc,Vs等编译器默认是#pragma pack(8),所以测试我们的规则会正常;注意gcc默认是#pragma pack(4),并且gcc只支持1,2,4对齐。套用三原则里计算的对齐值是不能大于#pragma pack指定的n值。

源文档 <http://blog.csdn.net/hairetz/article/details/4084088>

测试:

// demo.cpp : 定义控制台应用程序的入口点。
// vs2010 #include "stdafx.h"
#include "stdlib.h"
#include <stdio.h> typedef struct bb
{
int id; //[0]....[3]
double weight; //[8].....[15]      原则1
float height; //[16]..[19],总长要为8的整数倍,补齐[20]...[23]     原则3//注意4字节对其的编译器里面最大基数为4。
}BB; typedef struct aa
{
char name[2]; //[0],[1]
int id; //[4]...[7]          原则1
double score; //[8]....[15]
short grade;//[16],[17]
BB b; //[24]......[47]          原则2
}AA; typedef struct zz
{
char name[2]; //[0],[1]
int id; //[4]...[7]          原则1
double score; //[8]....[15]
short grade;//[16],[17]
BB b; //[24]......[47]          原则2
char a;
}ZZ; int _tmain(int argc, _TCHAR* argv[])
{
AA a;
BB b;
ZZ z; printf("sizeof(a) = %d, sizeof(BB) = %d\n",sizeof(a),sizeof(BB));
printf("sizeof(z) = %d\n",sizeof(z)); printf("size max = double = %d\n",sizeof(double) ); system("pause"); return 0;
} /**
sizeof(a) = 48, sizeof(BB) = 24
sizeof(z) = 56
size max = double = 8
请按任意键继续. . .
**/

  

// demo.cpp : 定义控制台应用程序的入口点。
// linux #include <stdio.h> typedef struct bb
{
int id; //[0]....[3]
double weight; //[8].....[15]      原则1
float height; //[16]..[19],总长要为8的整数倍,补齐[20]...[23]     原则3//注意4字节对其的编译器里面最大基数为4。
}BB; typedef struct aa
{
char name[2]; //[0],[1]
int id; //[4]...[7]          原则1
double score; //[8]....[15]
short grade;//[16],[17]
BB b; //[24]......[47]          原则2
}AA; typedef struct zz
{
char name[2]; //[0],[1]
int id; //[4]...[7]          原则1
double score; //[8]....[15]
short grade;//[16],[17]
BB b; //[24]......[47]          原则2
char a;
}ZZ; int main(int argc, char* argv[])
{
AA a;
BB b;
ZZ z; printf("sizeof(a) = %d, sizeof(BB) = %d\n",sizeof(a),sizeof(BB));
printf("sizeof(z) = %d\n",sizeof(z)); printf("size max = double = %d\n",sizeof(double) ); return 0;
} /**
root@oucaijun:/work/dcc# gcc *.c; ./a.out
sizeof(a) = 36, sizeof(BB) = 16
sizeof(z) = 40
size max = double = 8
**/

  

c语言,内存字节对齐的更多相关文章

  1. C语言:内存字节对齐详解[转载]

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

  2. C语言:内存字节对齐详解

    转:http://blog.csdn.net/arethe/article/details/2548867 一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论 ...

  3. 【C语言】字节对齐(内存对齐)

    数据对齐 1.  对齐原则: [原则1]数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma p ...

  4. 转载:C语言的字节对齐及#pragma pack的使用

    C语言的字节对齐及#pragma pack的使用   C编译器的缺省字节对齐方式(自然对界) 在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间. 在结构中,编译器为结构的每个成员 ...

  5. C++:struct和union 内存字节对齐问题

    转自:http://blog.csdn.net/wangyanguiyiyang/article/details/53312049 struct内存对齐问题 1:数据成员对齐规则:结构(struct) ...

  6. C++内存字节对齐规则

    为什么要进行内存对齐以及对齐规则 C/C++—— 内存字节对齐规则 C++内存字节对齐规则

  7. C语言之字节对齐

    在C语言编程中,有时为了达到减少运行的时间的目的,需要浪费一些空间:而有时为了节省空间,使它的运行时间增长.而字节对齐则是为了访问效率,用空间换取时间. 要掌握字节对齐,首先得明确一下四个概念: 1. ...

  8. struct/class等内存字节对齐问题详解

    问题引入 定义一个结构体的一般形式为: struct 结构体名 { //类型说明符 成员名; }; 例如有如下结构体: struct Stu { int id; char sex; float hig ...

  9. 【C语言】字节对齐问题(以32位系统为例)

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

随机推荐

  1. Mysql 外键设置

    MySql外键设置详解 (1) 外键的使用: 外键的作用,主要有两个:    一个是让数据库自己通过外键来保证数据的完整性和一致性    一个就是能够增加ER图的可读性    有些人认为外键的建立会给 ...

  2. The reference to entity "characterEncoding" must end with the ';' delimiter

    数据源配置时加上编码转换格式后出问题了: The reference to entity "characterEncoding" must end with the ';' del ...

  3. 解析request的反馈信息

    Map<String,String> params = new HashMap<String,String>(); Map requestParams = request.ge ...

  4. 设计模式总结4--singleton pattern

    单例模式 保证每个类只有一个实例,并提供一个全局访问点 第一步 构造方法私有化第二步 公有化静态方法获取的实例 懒汉式  public class Bank{ private Bank(){} pri ...

  5. The Priest Mathematician

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31329#problem/F f[0] = 1 , f[ i ] = f[ i - 1 ] ...

  6. android应用如何启动另外一个apk应用

    在开发的过程中,经常会遇到在一个应用中启动另外一个apk应用的情况 问题的核心点在于我们要拿到第三方apk的package名称跟class名称, 如:package名称是com.funcity.tax ...

  7. Hibernate级联操作和载入机制(二) cascade and fetch

    上一篇介绍了Hibernate持久化对象时候的级联操作.本篇介绍读取时候的级联操作. 还是用上一篇的样例.一份问卷有多个问题.可是每一个问题仅仅能属于一份问卷. 我们先看測试用例: @Test pub ...

  8. 二分图最大匹配 hdoj 1045

    题目:hdoj1045 题意:给出一个图.当中有 . 和 X 两种,. 为通路,X表示墙,在当中放炸弹,然后炸弹不能穿过墙.问你最多在图中能够放多少个炸弹? 分析:这道题目是在上海邀请赛的题目的数据简 ...

  9. 嵌入式:nfs挂载开发板的几个陷阱

    1. host没有设置好,这个比较容易排查到. 开启portmap帮助网络应用程序找到正确的通讯端口: 开启nfs-kernel-server服务: 开启设置要export出去的服务目录. sudo ...

  10. 《算法导论》读书笔记之图论算法—Dijkstra 算法求最短路径

    自从打ACM以来也算是用Dijkstra算法来求最短路径了好久,现在就写一篇博客来介绍一下这个算法吧 :) Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的 ...