结构体字节对齐

  在用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

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<

pragma pack (2) /指定按2字节对齐/

struct C
{
char b;
int a;
short c;
};

pragma pack () /取消指定对齐,恢复缺省对齐/sizeof(struct C)值是8。

修改对齐值为1:

pragma pack (1) /指定按1字节对齐/

struct D
{
char b;
int a;
short c;
};

pragma pack () /取消指定对齐,恢复缺省对齐/

sizeof(struct D)值为7。ARM下的对齐处理,可以使用 __packed,(_packed有可能是编译器关键字 )

typedef struct
{
char x;
int y;
}struct1;

typedef __packed struct
{
char x;
int y;
}struct2;在32位的ARM SDT编译器中
sizeof(struct1)值为8
sizeof(struct2)值为5;

__packed是进行一字节对齐。使用_packed一般会以降低运行性能为代价,由于大多数cpu处理数据在合适的字节边界数的情况下会更有效,packed的使用会破坏这种自然的边界数。

typedef __packed struct (结构体字节对齐)(转)相关推荐

  1. 结构体字节对齐(转)

    结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是 ...

  2. 指定结构体字节对齐方式

    指定结构体字节对齐方式 #pragma pack(push,1) typedef struct  { int b; char a;  }struct_t1; #pragma pack(pop)

  3. 一文了解结构体字节对齐

    结构体字节对齐详解 表述如有不正确的地方,欢迎批评指正. C++/C 常见的基本数据类型: bool short (short int) int long (long int) long long ( ...

  4. mysql字节对齐_结构体字节对齐(转)

    结构体字节对齐 在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题.从理论上讲,对于任何变量的访问都可以从任何地址开始访问,但是 ...

  5. C语言结构体字节对齐规则

    C语言结构体字节对齐规则 基本规则 规则1 :结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的地方(比如int在 ...

  6. c/c++下取消结构体字节对齐方法

    c/c++下取消结构体字节对齐方法 在c/c++下编译器会默认地对结构体进行对齐,其对齐的方法跟平台具体的特性有关,本文主要介绍结构体不进行对齐的方法. 1.结构体字节不进行对齐的用途 (1).减小内 ...

  7. C语言结构体字节对齐

      默认字节对齐 C语言结构体字节对齐是老生常谈的问题了,也是高频面试题,现在我们来深入研究这个问题,彻底弄懂到底是怎么回事,给你一个结构体定义和平台机器位数就能手动计算出结构体占用字节数,现在我们不 ...

  8. 结构体字节对齐详解【含实例】

    一.前言 结构体字节对齐属于老生常谈的问题,看似简单,却很容易忘记.而且因为结构体使用的普遍性,使得字节对齐也成为了一个不得不谈的话题. 二.什么是结构体字节对齐 假设现在有一个结构体如下,问你它的一 ...

  9. c/c++教程 - 1.10 结构体 使用typedef定义struct结构体 结构体数组 结构体指针 结构体嵌套 结构体做函数参数 结构体const

    十二.结构体 (1)结构体定义和使用 基本概念:结构体属于用户自定义的数据类型,允许用户存储不同的数据类型. 参考视频:https://www.bilibili.com/video/BV1et411b ...

最新文章

  1. WF 创建 SQL 持久性数据库
  2. 6.2 常见多媒体标准及压缩技术
  3. 前端学习(3180):ant-design介绍3
  4. Python str和bytes的相互转换
  5. Java并发(五)——锁
  6. Java String substring()方法示例
  7. js 判断浏览器是否滚动到底部
  8. 双点双向重分发中的次优路径和环路问题
  9. mysql redis binlog_基于binlog的canal到redis的同步
  10. python验证软件签名
  11. C语言之switch语句用法
  12. 使用python批量压缩图片文件
  13. js replace 中文分号_关于js分号的问题?
  14. sql 同义词使用_使用同义词简化SQL Server代码
  15. 刨根系列之volatile详解
  16. html表格标题居于标题左侧,css如何设置表格标题(caption标签)的位置
  17. linux cpu大小,如何查看linux cpu大小
  18. 软件工程实践2019第一次作业
  19. 湖南人与江西人,关系有多密切?回顾四省填湘的历史
  20. 全国各地的五十种面条大全

热门文章

  1. Maths | 病态问题和条件数
  2. Kubernetes 触发 OOMKilled(内存杀手)如何排除故障
  3. socket setSoTimeout方法
  4. 最好的游泳耳机推荐,四大公认好用的游泳耳机推荐
  5. html中加横线粗细控制,html中hr怎么设置粗细
  6. socket编程二十二:socket编程实现文件传输功能
  7. 今天去一个物流公司参观的一些体会
  8. Mysql怎么把微信昵称(带emoji表情)保存到数据库,亲测可用
  9. 双树复小波变换——详细分析
  10. 苹果13和苹果14的差异