C++中的字节对齐
本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三二一、小鱼)相关研究、学习内容所做的笔记,欢迎广大朋友指正!
字节对齐
1. 基本概念
字节对齐:计算机存储系统中以Byte为单位存储数据,不同数据类型所占的空间不同,如:整型(int)数据占4个字节,字符型(char)数据占一个字节,短整型(short)数据占两个字节,等等。计算机为了高速的读写数据,默认情况下将数据存放在某个地址的起始位置,如:整型数据(int)默认存储在地址能被4整除的起始位置,字符型数据(char)能够存放在不论什么地址位置(被1整除),短整型(short)数据存储在地址能被2整除的起始位置。这就是默认字节对齐方式。
2. 举例说明
非常显然默认对齐方式会浪费非常多空间,比如例如以下结构:
struct student
{
char name[5];
int num;
short score;
}
本来仅仅用了11bytes(5+4+2)的空间,可是因为int型默认4字节对齐,存放在地址能被4整除的起始位置,即:假设name[5]从0開始存放,它占5bytes,而num则从第8(偏移量)个字节開始存放。所以sizeof(student)=16。于是中间空出几个字节闲置着。但这样便于计算机高速读写数据,是一种以空间换取时间的方式。其数据对齐例如以下图:
|char|char|char|char|
|char|----|----|----|
|--------int--------|
|--short--|----|----|
假设我们将结构体中变量的顺序改变为:
struct student
{
int num;
char name[5];
short score;
}
则,num从0開始存放,而name从第4(偏移量)个字节開始存放,连续5个字节,score从第10(偏移量)開始存放,故sizeof(student)=12。其数据对齐例如以下图:
|--------int--------|
|char|char|char|char|
|char|----|--short--|
假设我们将结构体中变量的顺序再次改为为:
struct student
{
int num;
short score;
char name[5];
}
则,sizeof(student)=12。其数据对齐例如以下图:
|--------int--------|
|--short--|char|char|
|char|char|char|----|
验证代码例如以下:
执行结果例如以下:
3. #pragma pack()命令
为了节省空间,我们能够在编码时通过#pragma pack()命令指定程序的对齐方式,括号里是对齐的字节数,若该命令括号里的内容为空,则为默认对齐方式。比如,对于上面第一个结构体,假设通过该命令手动设置对齐字节数例如以下:
#pragma pack(2) //设置2字节对齐
struct strdent
{
char name[5]; //本身1字节对齐,比2字节对齐小,按1字节对齐
int num; //本身4字节对齐,比2字节对齐大,按2字节对齐
short score; //本身也2字节对齐,仍然按2字节对齐
}
#pragma pack() //取消设置的字节对齐方式
则,num从第6(偏移量)个字节開始存放,score从第10(偏移量)个字节開始存放,故sizeof(student)=12,其数据对齐例如以下图:
|char|char|
|char|char|
|char|-----|
|----int----|
|----int----|
|--short---|
这样改变默认的字节对齐方式能够更充分地利用存储空间,可是这会减少计算机读写数据的速度,是一种以时间换取空间的方式。
验证代码例如以下:
执行结果例如以下:
若该为#pragma pack(1),则执行结果例如以下:
4. 样例
程序例如以下:
该样例採取默认对齐方式,执行结果例如以下:
说明:静态变量存放在全局数据区内,而sizeof计算栈中分配的空间的大小,故不计算在内。
若加上#pragma pack(2)命令,则执行结果例如以下:
相关文章
- 【c++STL——第六讲】deque系列 (常用知识点总结)
- C#调用C++的dll
- 托管C++线程锁实现 c++11线程池
- [c++菜鸟]《Accelerate C++》习题解答
- 【侯捷】C++面向对象高级编程(下)
- C++第9周项目4参考——本月有几天?
- C++中值传递、指针传递和引用传递的比较详解
- C++图像缩放(StretchBlt,StretchDIBits,双线性内插法)
- c++中调用Com组件的方法详解
- 开源免费的C/C++网络库(c/c++ sockets library)补充
- C++中的std::lower_bound()和std::upper_bound()函数
- 使用c++filt命令还原C++编译后的函数名
- 【C++】AVL树,平衡二叉树详细解析
- 为什么一定要调用 setlocale 呢? 因为在 C/C++ 语言标准中定义了其运行时的字符集环境为 "C" ,也就是 ASCII 字符集的一个子集。使用setlocal改变整个应用程序的字符集编码方式(wcstombs使用前要设置 setlocale (LC_ALL, "chs"); )
- 为python编译C++模块时一定要注意的事情—————不要在anaconda环境下使用cmake来编译C++扩展模块!!!
- 轻松编写 C++ 单元测试
- 在CC++中char 、short 、int各占多少个字节