[C&C++]C语言字节对齐#pragma pack()



原创文章,欢迎转载。转载请注明:转载自 祥的博客

原文链接:https://blog.csdn.net/humanking7/article/details/80979517



1.现象

1.1. 测试代码

#include <iostream>
using namespace std;


//默认对齐方式
typedef struct
{
    double a;//8个字节
    char   b;//1个字节
    float  c;//4个字节
}DataType;


//8字节对齐方式
#pragma pack(push)
#pragma pack(8)
typedef struct
{
    double a;//8个字节
    char   b;//1个字节
    float  c;//4个字节
}DataType_8;
#pragma pack(pop)

//4字节对齐方式
#pragma pack(push)
#pragma pack(4)
typedef struct
{
    double a;//8个字节
    char   b;//1个字节
    float  c;//4个字节
}DataType_4;
#pragma pack(pop)

//2字节对齐方式
#pragma pack(push)
#pragma pack(2)
typedef struct
{
    double a;//8个字节
    char   b;//1个字节
    float  c;//4个字节
}DataType_2;
#pragma pack(pop)

//1字节对齐方式
#pragma pack(push)
#pragma pack(1)
typedef struct
{
    double a;
    char   b;
    float  c;
}DataType_1;
#pragma pack(pop)


int main()
{

    cout << "sizeof( DataType ) = " << sizeof(DataType) << endl;
    cout << "sizeof( DataType_1 ) = " << sizeof(DataType_1) << endl;
    cout << "sizeof( DataType_2 ) = " << sizeof(DataType_2) << endl;
    cout << "sizeof( DataType_4 ) = " << sizeof(DataType_4) << endl;
    cout << "sizeof( DataType_8 ) = " << sizeof(DataType_8) << endl;



    return 0;
}

1.2. 结果

sizeof( DataType ) = 16
sizeof( DataType_1 ) = 13
sizeof( DataType_2 ) = 14
sizeof( DataType_4 ) = 16
sizeof( DataType_8 ) = 16

1.3. 注意

各家编译器(VSgcc)对与packpop的解释和支持都是不一样的。
Visual Studio 2013 http://msdn.microsoft.com/en-us/library/2e70t5y1(v=vs.120).aspx

具体可以看看这个博文:http://blog.chinaunix.net/uid-14949191-id-3969367.html

不过在下认为,最主要的还是要多测试,如果换了编译环境,一定要测试先行,血的教训。

2. 相关概念

字节对齐:

现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

结构体对齐:

在C语言中,结构体是种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如数组、结构体、联合等)的数据单元。编译器为结构体的每个成员按照其自然边界(alignment)分配空间。各成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
字节对齐的问题主要就是针对结构体。

引用一些博客博文说明

四个重要的基本概念:

  1. 数据类型自身的对齐值:char型数据自身对齐值为1字节,short型数据为2字节,int/float型为4字节,double型为8字节。
  2. 结构体或类的自身对齐值:其成员中自身对齐值最大的那个值。
  3. 指定对齐值:#pragma pack (value)时的指定对齐值value。
  4. 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值}。

结构体字节对齐的细节和具体编译器实现相关,但一般而言满足三个准则:

  1. 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
  2. 结构体每个成员相对结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
  3. 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节{trailing padding}。

3. 扩展概念

位域对齐

有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1两种状态,用一位二进位即可。为了节省存储空间和处理简便,C语言提供了一种数据结构,称为“位域”或“位段”。

位域是一种特殊的结构成员或联合成员(即只能用在结构或联合中),用于指定该成员在内存存储时所占用的位数,从而在机器内更紧凑地表示数据。每个位域有一个域名,允许在程序中按域名操作对应的位。这样就可用一个字节的二进制位域来表示几个不同的对象。

可以继续查看相关博文,在下现在没有对此没有需求,先Mark一下:相关博文


赞赏码New

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值