OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 17890|回复: 43

[转]结构体字节对齐

  [复制链接]

230

主题

1952

帖子

10

精华

论坛元老

Rank: 8Rank: 8

积分
4562
金钱
4562
注册时间
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字节对齐
[mw_shl_code=c,true]typedefstructnode { }S;[/mw_shl_code]


typedefstructnode1
{
inta;
charb;
shortc;
}S1;
typedefstructnode2
{
chara;
intb;
shortc;
}S2;
typedefstructnode3
{
inta;
shortb;
staticintc;
}S3;
typedefstructnode4
{
boola;
S1 s1;
shortb;
}S4;
[mw_shl_code=c,true]typedefstructnode5 { boola; S1 s1; doubleb; intc; }S5;[/mw_shl_code]


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:389063473Email:389063473@qq.com
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

126

主题

825

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

使用道具 举报

2

主题

27

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

6

主题

23

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

4

主题

19

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
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

主题

1012

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
2382
金钱
2382
注册时间
2012-11-22
在线时间
403 小时
发表于 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

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

使用道具 举报

24

主题

91

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

3

主题

24

帖子

0

精华

初级会员

Rank: 2

积分
101
金钱
101
注册时间
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 | 显示全部楼层
不错
回复 支持 反对

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

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

使用道具 举报

1

主题

7

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

0

主题

7

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
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

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
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

精华

新手上路

积分
22
金钱
22
注册时间
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

精华

新手上路

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

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

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

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

1

主题

4

帖子

0

精华

新手入门

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

使用道具 举报

18

主题

238

帖子

3

精华

金牌会员

Rank: 6Rank: 6

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

使用道具 举报

3

主题

8

帖子

0

精华

新手上路

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

使用道具 举报

17

主题

343

帖子

0

精华

高级会员

Rank: 4

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

使用道具 举报

1

主题

108

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

9

主题

30

帖子

0

精华

中级会员

Rank: 3Rank: 3

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

使用道具 举报

7

主题

21

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

1

主题

3

帖子

0

精华

新手上路

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

使用道具 举报

86

主题

980

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

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

使用道具 举报

4

主题

14

帖子

0

精华

初级会员

Rank: 2

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

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

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

使用道具 举报

10

主题

271

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

使用道具 举报

34

主题

322

帖子

0

精华

金牌会员

Rank: 6Rank: 6

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

使用道具 举报

0

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2018-11-19
在线时间
2 小时
发表于 2018-11-28 10:28:04 | 显示全部楼层
很全面啊!!!
回复 支持 反对

使用道具 举报

0

主题

17

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2019-7-8
在线时间
7 小时
发表于 2019-7-15 12:29:27 | 显示全部楼层
赞赞赞
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-29 03:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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