博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
转载:结构体的字节对齐
阅读量:4708 次
发布时间:2019-06-10

本文共 3594 字,大约阅读时间需要 11 分钟。

声明:学习中从原子那拿来的

 

结构体字节对齐

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

内存对齐的原因:

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

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

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

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

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

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

 

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

1.test1 空结构体

typedef
struct
node
{
 
}S;

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

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

2.test2

typedef
struct
node1
{
int
a;
char
b;
short
c;
}S1;

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

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

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

总共占8字节

3.test3

typedef
struct
node2
{
char
a;
int
b;
short
c;
}S2;

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

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

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

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

总共占12个字节

4.test4 含有静态数据成员

typedef
struct
node3
{
int
a;
short
b;
static
int
c;
}S3;

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

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

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

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

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

typedef
struct
node4
{
bool
a;
S1 s1;
short
b;
}S4;

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

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

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

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

6.test6

typedef
struct
node5
{
bool
a;
S1 s1;
double
b;
int
c;
}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),对于下面的结构体

typedef
struct
node5
{
bool
a;
S1 s1;
double
b;
int
c;
}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>
using
namespace
std;
//#pragma pack(4) //设置4字节对齐
//#pragma pack() //取消4字节对齐
 
typedef
struct
node
{
 
}S;
 
typedef
struct
node1
{
int
a;
char
b;
short
c;
}S1;
 
typedef
struct
node2
{
char
a;
int
b;
short
c;
}S2;
 
typedef
struct
node3
{
int
a;
short
b;
static
int
c;
}S3;
 
typedef
struct
node4
{
bool
a;
S1 s1;
short
b;
}S4;
 
typedef
struct
node5
{
bool
a;
S1 s1;
double
b;
int
c;
}S5;
 
 
 
int
main(
int
argc,
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;
return
0;
}

转载于:https://www.cnblogs.com/wwjdwy/p/3140691.html

你可能感兴趣的文章
C#中的委托和事件(续)
查看>>
python--MySql
查看>>
机器学习 - pycharm, pyspark, spark集成篇
查看>>
mysql explain 中key_len的计算
查看>>
实验一
查看>>
Linux内核--网络栈实现分析(九)--传输层之UDP协议(下)
查看>>
Lua -- 简洁、轻量、可扩展的脚本语言
查看>>
Python 2.7_Second_try_爬取阳光电影网_获取电影下载地址并写入文件 20161207
查看>>
[Fiddler] 开启Fiddler抓包的时候产品报“证书错误”
查看>>
打包苦逼活
查看>>
Oracle Certified Java Programmer 经典题目分析(二)
查看>>
第二十五章补充内容 17位字段
查看>>
灰色预测
查看>>
css随笔
查看>>
基于自己封装的select下拉选择的省市区三级联动效果,兼容IE
查看>>
初识Python
查看>>
nodejs+mysql入门实例(改)
查看>>
表达式语言
查看>>
jQuery EasyUI实现关闭全部tabs
查看>>
iOS项目之WKWebView替换UIWebView相关
查看>>