OpenEdv-开源电子网

 找回密码
 立即注册

扫一扫,访问微社区

正点原子新作:阿波罗STM32F767&F429&探索者STM32F4开发板&赶快来下载资料哦。

查看: 10001|回复: 41

[转]结构体字节对齐

  [复制链接]

  离线 

230

主题

1952

帖子

10

精华

论坛元老

Rank: 8Rank: 8

积分
4561
金钱
4561
注册时间
2010-12-14
在线时间
32 小时
发表于 2013-3-14 20:21:10 | 显示全部楼层 |阅读模式
正点原子公众号
  结构体字节对齐

在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何 变量的访问都可以从任何地址开始访问,但是事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列, 而不是简单地顺序排列,这就是内存对齐。

内存对齐的原因:

1)某些平台只能在特定的地址处访问特定类型的数据;

2)提高存取数据的速度。比如有的平台每次都是从偶地址处读取数据,对于一个int型的变量,若从偶地址单元处存放,则只需一个读取周期即可读取该变量;但是若从奇地址单元处存放,则需要2个读取周期读取该变量。

win32平台下的微软C编译器对齐策略:

1)结构体变量的首地址能够被其最宽数据类型成员的大小整除。编译器在为结构体变量开辟空间时,首先找到结构体中最宽的数据类型,然后寻找内存地址能被该数据类型大小整除的位置,这个位置作为结构体变量的首地址。而将最宽数据类型的大小作为对齐标准。

2)结构体每个成员相对结构体首地址的偏移量(offset)都是每个成员本身大小的整数倍,如有需要会在成员之间填充字节。编译器在为结构体成员开辟空 间时,首先检查预开辟空间的地址相对于结构体首地址的偏移量是否为该成员大小的整数倍,若是,则存放该成员;若不是,则填充若干字节,以达到整数倍的要 求。

3)结构体变量所占空间的大小必定是最宽数据类型大小的整数倍。如有需要会在最后一个成员末尾填充若干字节使得所占空间大小是最宽数据类型大小的整数倍。

下面看一下sizeof在计算结构体大小的时候具体是怎样计算的

1.test1 空结构体

?
typedefstructnode
{
}S;

则sizeof(S)=1;或sizeof(S)=0;

在C++中占1字节,而在C中占0字节。

2.test2

?
typedefstructnode1
{
inta;
charb;
shortc;
}S1;

则sizeof(S1)=8。这是因为结构体node1中最长的数据类型是int,占4个字节,因此以4字节对齐,则该结构体在内存中存放方式为

|--------int--------| 4字节

|char|----|--short-| 4字节

总共占8字节

3.test3

?
typedefstructnode2
{
chara;
intb;
shortc;
}S2;

则siezof(S3)=12.最长数据类型为int,占4个字节。因此以4字节对齐,其在内存空间存放方式如下:

|char|----|----|----| 4字节

|--------int--------| 4字节

|--short--|----|----| 4字节

总共占12个字节

4.test4 含有静态数据成员

?
typedefstructnode3
{
inta;
shortb;
staticintc;
}S3;

则sizeof(S3)=8.这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。其在内存中存储方式如下:

|--------int--------| 4字节

|--short-|----|----| 4字节

而变量c是单独存放在静态数据区的,因此用siezof计算其大小时没有将c所占的空间计算进来。

5.test5 结构体中含有结构体

?
typedefstructnode4
{
boola;
S1 s1;
shortb;
}S4;

则sizeof(S4)=16。是因为s1占8字节,而s1中最长数据类型为int,占4个字节,bool类型1个字节,short占2字节,因此以4字节对齐,则存储方式为

|-------bool--------| 4字节

|-------s1----------| 8字节

|-------short-------| 4字节

6.test6

?
typedefstructnode5
{
boola;
S1 s1;
doubleb;
intc;
}S5;

则sizeof(S5)=32。是因为s1占8字节,而s1中最长数据类型为int,占4字节,而double占8字节,因此以8字节对齐,则存放方式为:

|--------bool--------| 8字节

|---------s1---------| 8字节

|--------double------| 8字节

|----int----|---------| 8字节

7.test7

若在程序中使用了#pragma pack(n)命令强制以n字节对齐时,默认情况下n为8.

则比较n和结构体中最长数据类型所占的字节大小,取两者中小的一个作为对齐标准。

若需取消强制对齐方式,则可用命令#pragma pack()

如果在程序开头使用命令#pragma pack(4),对于下面的结构体

?
typedefstructnode5
{
boola;
S1 s1;
doubleb;
intc;
}S5;

则sizeof(S5)=24.因为强制以4字节对齐,而S5中最长数据类型为double,占8字节,因此以4字节对齐。在内存中存放方式为:

|-----------a--------| 4字节

|--------s1----------| 4字节

|--------s1----------| 4字节

|--------b-----------| 4字节

|--------b-----------| 4字节

|---------c----------| 4字节

总结一下,在计算sizeof时主要注意一下几点:

1)若为空结构体,则只占1个字节的单元

2)若结构体中所有数据类型都相同,则其所占空间为 成员数据类型长度×成员个数

若结构体中数据类型不同,则取最长数据类型成员所占的空间为对齐标准,数据成员包含另一个结构体变量t的话,则取t中最 长数据类型与其他数据成员比较,取最长的作为对齐标准,但是t存放时看做一个单位存放,只需看其他成员即可。

3)若使用了#pragma pack(n)命令强制对齐标准,则取n和结构体中最长数据类型占的字节数两者之中的小者作为对齐标准。

另外除了结构体中存在对齐之外,普通的变量存储也存在字节对齐的情况,即自身对齐。编译器规定:普通变量的存储首地址必须能被该变量的数据类型宽度整除。

测试程序:

?
/*测试sizeof运算符 2011.10.1*/
#include <iostream>
usingnamespacestd;
//#pragma pack(4) //设置4字节对齐
//#pragma pack() //取消4字节对齐
[C] 纯文本查看 复制代码
typedefstructnode
{
}S;


typedefstructnode1
{
inta;
charb;
shortc;
}S1;
typedefstructnode2
{
chara;
intb;
shortc;
}S2;
typedefstructnode3
{
inta;
shortb;
staticintc;
}S3;
typedefstructnode4
{
boola;
S1 s1;
shortb;
}S4;
[C] 纯文本查看 复制代码
typedefstructnode5
{
boola;
S1 s1;
doubleb;
intc;
}S5;


intmain(intargc,char*argv[])
{
cout<<sizeof(char)<<" "<<sizeof(short)<<" "<<sizeof(int)<<" "<<sizeof(float)<<" "<<sizeof(double)<<endl;
S s;
S1 s1;
S2 s2;
S3 s3;
S4 s4;
S5 s5;
cout<<sizeof(S3)<<endl;
cout<<sizeof(s)<<" "<<sizeof(s1)<<" "<<sizeof(s2)<<" "<<sizeof(s3)<<" "<<sizeof(s4)<<" "<<sizeof(s5)<<endl;
return0;
}

我是开源电子网?网站管理员,对网站有任何问题,请与我联系! QQ:389063473 Email:389063473@qq.com
回复

使用道具 举报

  离线 

123

主题

817

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1649
金钱
1649
注册时间
2012-10-28
在线时间
57 小时
发表于 2013-3-15 08:30:30 | 显示全部楼层
雖然看不懂,但是還是要頂的
坚持学习!就能成功!
回复 支持 反对

使用道具 举报

  离线 

2

主题

27

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2013-3-14
在线时间
0 小时
发表于 2013-3-15 22:37:53 | 显示全部楼层
学习了,mark
回复 支持 反对

使用道具 举报

  离线 

4

主题

17

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2012-4-15
在线时间
0 小时
发表于 2013-4-5 13:06:03 | 显示全部楼层
 哈哈,真的是理解透彻啊!
回复 支持 反对

使用道具 举报

  离线 

4

主题

19

帖子

0

精华

初级会员

Rank: 2

积分
55
金钱
55
注册时间
2012-12-5
在线时间
0 小时
发表于 2013-4-16 23:31:17 | 显示全部楼层
正点原子公众号
不错
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2012-11-3
在线时间
0 小时
发表于 2013-4-17 15:49:13 | 显示全部楼层
学习了,谢谢!!
回复 支持 反对

使用道具 举报

  离线 

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2013-5-1
在线时间
0 小时
发表于 2013-5-28 15:08:37 | 显示全部楼层
讲的很清楚啊,以前一直认为是顺序徘下来的。。。
回复 支持 反对

使用道具 举报

  离线 

54

主题

968

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1715
金钱
1715
注册时间
2012-11-22
在线时间
217 小时
发表于 2013-6-10 18:02:33 | 显示全部楼层
呵呵,上次没看懂,今天看懂了,嘿嘿。
态度决定一切 四人行
回复 支持 反对

使用道具 举报

  离线 

4

主题

7

帖子

0

精华

新手入门

积分
48
金钱
48
注册时间
2013-8-8
在线时间
1 小时
发表于 2013-8-8 19:43:56 | 显示全部楼层
好东西呀!
回复 支持 反对

使用道具 举报

  离线 

7

主题

171

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2013-8-9
在线时间
3 小时
发表于 2013-8-9 17:55:46 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

  离线 

23

主题

90

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
355
金钱
355
注册时间
2013-6-19
在线时间
46 小时
发表于 2013-8-10 19:01:43 | 显示全部楼层
cool
回复 支持 反对

使用道具 举报

  离线 

3

主题

22

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2013-5-6
在线时间
18 小时
发表于 2013-8-12 16:09:56 | 显示全部楼层
简单易懂!谢了!
回复 支持 反对

使用道具 举报

  离线 

0

主题

9

帖子

0

精华

新手入门

积分
29
金钱
29
注册时间
2013-8-26
在线时间
0 小时
发表于 2013-8-26 09:56:00 | 显示全部楼层
pl
回复 支持 反对

使用道具 举报

  离线 

5

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
67
金钱
67
注册时间
2013-9-13
在线时间
4 小时
发表于 2013-9-15 20:49:56 | 显示全部楼层
不错
回复 支持 反对

使用道具 举报

  离线 

0

主题

3

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2013-12-9
在线时间
0 小时
发表于 2013-12-9 09:26:04 | 显示全部楼层
不错,学习了
回复 支持 反对

使用道具 举报

  离线 

1

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
73
金钱
73
注册时间
2013-10-8
在线时间
14 小时
发表于 2013-12-28 19:58:55 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

  离线 

0

主题

7

帖子

0

精华

新手入门

积分
36
金钱
36
注册时间
2013-12-9
在线时间
1 小时
发表于 2014-1-16 21:28:27 | 显示全部楼层
好像没看太懂,以后再来,先了解哈
回复 支持 反对

使用道具 举报

  离线 

14

主题

58

帖子

1

精华

中级会员

Rank: 3Rank: 3

积分
293
金钱
293
注册时间
2014-1-24
在线时间
2 小时
发表于 2014-2-9 11:41:43 | 显示全部楼层
呵呵,多谢楼主,很透彻!
回复 支持 反对

使用道具 举报

  离线 

30

主题

707

帖子

1

精华

新手入门

积分
15
金钱
15
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-2-10 10:49:10 | 显示全部楼层
回复【楼主位】Admin:
---------------------------------
不错 mark
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

  离线 

0

主题

3

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2014-3-7
在线时间
0 小时
发表于 2014-3-12 15:09:02 | 显示全部楼层
没看懂。。。。下次再来
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-3-20
在线时间
0 小时
发表于 2014-3-22 20:33:34 | 显示全部楼层
不明觉厉
回复 支持 反对

使用道具 举报

  离线 

17

主题

93

帖子

0

精华

初级会员

Rank: 2

积分
181
金钱
181
注册时间
2013-10-9
在线时间
0 小时
发表于 2014-3-26 10:54:46 | 显示全部楼层
MARK
回复 支持 反对

使用道具 举报

  离线 

2

主题

10

帖子

0

精华

新手入门

积分
38
金钱
38
注册时间
2014-4-12
在线时间
0 小时
发表于 2014-4-22 09:21:58 | 显示全部楼层
看不懂  555
回复 支持 反对

使用道具 举报

  离线 

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-5-14
在线时间
0 小时
发表于 2014-5-14 14:06:29 | 显示全部楼层
mark..
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-6-30
在线时间
0 小时
发表于 2014-6-30 22:28:55 | 显示全部楼层
不明觉厉,下次再看
回复 支持 反对

使用道具 举报

  离线 

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2014-7-27
在线时间
0 小时
发表于 2014-7-27 20:54:01 | 显示全部楼层
受教了~谢谢
回复 支持 反对

使用道具 举报

  离线 

0

主题

2

帖子

0

精华

新手入门

积分
23
金钱
23
注册时间
2014-7-31
在线时间
0 小时
发表于 2014-7-31 08:26:59 | 显示全部楼层
非常好 mark
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-7-28
在线时间
0 小时
发表于 2014-8-3 17:02:26 | 显示全部楼层
好东西  哈哈哈
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-8-4
在线时间
2 小时
发表于 2014-8-4 21:39:39 | 显示全部楼层
mark一下 准备学习
回复 支持 反对

使用道具 举报

  离线 

1

主题

4

帖子

0

精华

新手入门

积分
32
金钱
32
注册时间
2014-8-20
在线时间
3 小时
发表于 2014-8-22 22:39:00 | 显示全部楼层
讲的真心很好,几乎讲到了可能遇到的每种情况
回复 支持 反对

使用道具 举报

  离线 

18

主题

239

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
1818
金钱
1818
注册时间
2014-8-5
在线时间
210 小时
发表于 2014-9-24 10:16:24 | 显示全部楼层
谢谢楼主分享,学习了 
回复 支持 反对

使用道具 举报

  离线 

3

主题

8

帖子

0

精华

新手入门

积分
40
金钱
40
注册时间
2014-9-20
在线时间
0 小时
发表于 2014-11-5 19:19:15 | 显示全部楼层
很好,学习了
回复 支持 反对

使用道具 举报

  离线 

17

主题

340

帖子

0

精华

高级会员

Rank: 4

积分
514
金钱
514
注册时间
2014-4-24
在线时间
12 小时
发表于 2014-11-22 20:26:19 | 显示全部楼层
学习啦!~~~
回复 支持 反对

使用道具 举报

  离线 

1

主题

108

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
307
金钱
307
注册时间
2012-11-8
在线时间
34 小时
发表于 2015-1-5 15:40:26 | 显示全部楼层
好东西,学习了
回复 支持 反对

使用道具 举报

  离线 

9

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
187
金钱
187
注册时间
2015-3-2
在线时间
27 小时
发表于 2015-3-4 21:20:40 | 显示全部楼层
下次再来理解理解
回复 支持 反对

使用道具 举报

  离线 

7

主题

21

帖子

0

精华

初级会员

Rank: 2

积分
87
金钱
87
注册时间
2015-7-17
在线时间
5 小时
发表于 2015-7-19 19:01:09 | 显示全部楼层
学习了,哈哈哈
回复 支持 反对

使用道具 举报

  离线 

1

主题

2

帖子

0

精华

新手入门

积分
26
金钱
26
注册时间
2014-6-29
在线时间
0 小时
发表于 2015-8-19 10:51:47 | 显示全部楼层
mark,学习一下
回复 支持 反对

使用道具 举报

  离线 

78

主题

902

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1529
金钱
1529
注册时间
2013-4-15
在线时间
107 小时
发表于 2015-8-24 14:07:16 | 显示全部楼层
赞一个,讲的不错,刚好在弄内存分配,遇到了字节对齐,版主讲的很清楚,学习了
合肥-文盲
回复 支持 反对

使用道具 举报

  离线 

4

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
72
金钱
72
注册时间
2015-9-18
在线时间
4 小时
发表于 2015-9-20 20:12:40 | 显示全部楼层
不错,顶一个。
回复 支持 反对

使用道具 举报

  离线 

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2015-10-23
在线时间
0 小时
发表于 2015-10-23 14:49:07 | 显示全部楼层
回复【8楼】冰封嗜魔:
---------------------------------
第一次看,蒙了,没懂
回复 支持 反对

使用道具 举报

  离线 

10

主题

125

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
448
金钱
448
注册时间
2015-5-14
在线时间
97 小时
发表于 2015-10-23 17:27:10 | 显示全部楼层
顶一下,慢慢看!
30年众生牛马,60年诸佛龙象!
回复 支持 反对

使用道具 举报

  离线 

16

主题

149

帖子

0

精华

高级会员

Rank: 4

积分
572
金钱
572
注册时间
2014-12-4
在线时间
182 小时
发表于 2017-8-22 17:12:26 | 显示全部楼层
mark        
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则




QQ|联系我们|手机版|官方淘宝店|新浪微博|微信公众平台|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2018-6-18 19:05

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表
/* */