`
king_tt
  • 浏览: 2083436 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

C语言内存字节对齐小结

 
阅读更多

在C语言面试和考试中经常会遇到内存字节对齐的问题。今天就来对字节对齐的知识进行小结一下。

首先说说为什么要对齐。为了提高效率,计算机从内存中取数据是按照一个固定长度的。以32位机为例,它每次取32个位,也就是4个字节(每字节8个位,计算机基础知识,别说不知道)。字节对齐有什么好处?以int型数据为例,如果它在内存中存放的位置按4字节对齐,也就是说1个int的数据全部落在计算机一次取数的区间内,那么只需要取一次就可以了。如图a-1。如果不对齐,很不巧,这个int数据刚好跨越了取数的边界,这样就需要取两次才能把这个int的数据全部取到,这样效率也就降低了。



图:a-1


图:a-2

内存对齐是会浪费一些空间的。但是这种空间上得浪费却可以减少取数的时间。这是典型的一种以空间换时间的做法。空间与时间孰优孰略这个每个人都有自己的看法,但是C语言既然采取了这种以空间换时间的策略,就必然有它的道理。况且,在存储器越来越便宜的今天,这一点点的空间上的浪费就不算什么了。

需要说明的是,字节对齐不同的编译器可能会采用不同的优化策略,以下以GCC为例讲解结构体的对齐.

一、原则:

1.结构体内成员按自身按自身长度自对齐。

自身长度,如char=1,short=2,int=4,double=8,。所谓自对齐,指的是该成员的起始位置的内存地址必须是它自身长度的整数倍。如int只能以0,4,8这类的地址开始

2.结构体的总大小为结构体的有效对齐值的整数倍

结构体的有效对齐值的确定:

1)当未明确指定时,以结构体中最长的成员的长度为其有效值

2)当用#pragma pack(n)指定时,以n和结构体中最长的成员的长度中较小者为其值。

3)当用__attribute__ ((__packed__))指定长度时,强制按照此值为结构体的有效对齐值

二、例子

1。

struct AA{

char a;

int b;

char c;

}aa

结果,sizeof(aa)=12

何解?首先假设结构体内存起始地址为0,那么地址的分布如下

0 a

1

2

3

4 b

5 b

6 b

7 b

8 c

9

10

11

char的字对齐长度为1,所以可以在任何地址开始,但是,int自对齐长度为4,必须以4的倍数地址开始。所以,尽管1-3空着,但b也只能从4开始。再加上c后,整个结构体的总长度为9,结构体的有效对齐值为其中最大的成员即int的长度4,所以,结构体的大小向上扩展到12,即9-11的地址空着。

2.

struct AA{

char a;

char c;

int b;

}aa

sizeof(aa)=8,为什么呢

0 a

1 c

2

3

4 b

5 b

6 b

7 b

因为c为char类型,字对齐长度为1,所以可以有效的利用1-3间的空格。看见了吧,变量定义的位置的不同时有可能影响结构体的大小的哦!


3.

#pragma pack(2)

struct AA{

char a;

int b;

char c;

}aa

sizeof(aa)=10,

为什么呢?a到c只占9字节长度,因为结构体的有效对齐长度在pack指定的2和int的4中取

较小的值2。故取2的倍数10。

如果当pack指定为8呢?那就仍然按4来对齐,结果仍然是12。


4.

struct AA{

char a;

int b;

char c;

}__attribute__((__8__))aa

sizeof(aa)=16,)

为咩?其实a到c仍然只占9字节长度,但结构体以8对齐,故取8的倍数16.

如果其指定2,则结果为10


如果pragma pack和__attribute__ 同时指定呢?以__attribute__ 的为准。

需要说明的是,不管pragma pack和__attribute__如何指定,结构体内部成员的自对齐仍然按照其自身的对齐值。


另外,不同的编译器可能会对内存的分布进行优化,

例如有些编译器会把立体1中的程序优化成例题2的样子。但这属于编译器的问题,

这里不做详细讨论。如果要作为编程的参考的话,最好当做编译器不会做优化,

尽量在保持代码清晰的情况下,自己手动将例题1优化成例题2的样子。

如果是做题的话,按照以上原则做就可以了,不用考虑不同编译器的特性。


分享到:
评论

相关推荐

    C语言讲义.doc

    1.1.23 指针小结 63 2 字符指针与字符串 64 2.1 指针和字符串 64 2.2 通过指针访问字符串数组 64 2.3 函数的参数为CHAR * 64 2.4 指针数组做为MAIN函数的形参 65 3 内存管理 65 3.1 作用域 65 3.1.1 auto自动变量 65...

    C语言程序设计标准教程

    在Turbo C中单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。 实型变量说明...

    嵌入式Linux C编程入门(第2版) PPT

    本章小结 70 动手练练 70 第3章 构建嵌入式linux系统 71 3.1 嵌入式系统开发环境的构建 71 3.1.1 嵌入式交叉编译环境搭建 71 3.1.2 minicom和超级终端配置及使用 76 3.1.3 宿主机服务配置 83 3.2...

    c++ 面试题 总结

    块式管理:把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程 序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。这样会造成很大的浪费,平均浪费了50%的...

    汇编语言入门到精通文档

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言教程(AoGo汇编网站)

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言教程Assembly Language

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言.chm 学习汇编语言入门

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言基础教程(8086).rar

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 十字...

    汇编语言教程-学习的极佳资料

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言基础教程 汇编语言基础教程

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言基础学习资料

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言教程.chm

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言教程

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    (chm)汇编语言全接触

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    80x86汇编语言教程

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

    汇编语言学习大全

     3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义  1 内存变量定义的一般形式  2 字节变量  3 字变量  4 双字变量  5 六字节变量  6 八字节变量  7 ...

Global site tag (gtag.js) - Google Analytics