c语言之字节对齐-初步认识

1.字节对齐的概念
(1)背景

当系统为我们划分一段连续内存空间时,cpu在访问内存空间数据理论上时可以从任意地址访问随机大小的数据。但是由于硬件方面和操作系统的问题,
CPU在读写内存的时候是以内存块来读取内存的,所以如果在读取了一个int数据紧接着又读取一个char型数据,那么可能cpu会直接读取到更多的地址。
然后再重新定位到char的内存地址上。当然,这是在每个数据都连续内存存放的情况下,显然,CPU的访问效率会降低很多。
(2)什么是字节对齐
为了提高CPU的内存访问效率。于是引入了字节(内存)对齐的概念,毫无疑问,字节对齐是通过消耗内存空间来换取CPU效率的一个手段。

2.字节对齐的准则
(1)基本数据类型的自身对齐值
(2)程序的指定对齐值(#pragma pack(value)时的value)
(3)自定义类型的自身对齐值(即结构体或类成员自身对齐值最大的值)
(4)自定义类型的有效对齐值(自定义类型的自身对齐值和指定对齐中较小的值)

3.字节对齐实例
(1)普通结构体对齐

struct Test1             // 对齐情况下为24,不对齐情况下为13,本身对齐值为8
{
    int a;                   // 4+4            4指定对齐值为4,自身对齐值为8
    double b;            // 8                8
    char c;                // 1+7            1+3            
};
对于struct Test结构体,按照我们猜想,整个结构体在内存中所占字节应该是4+8+1=13,但是我们用printf("%d\n",sizeof(struct Test));输出24。
别忘了内存对我们的数据对齐了。由于我们没有对程序指定对齐值,那我们先看变量a,自身对齐值4bytes,变量b占用8bytes,这时候自身对齐值为8。
需要在a的4字节后面再填充4个字节。c占一个字节,后面没有数据。这个时候Test中成员所占内存空间就是4+4+8+1=17。
但是结构体本身需要按照最宽数据成员对齐值的整数倍对齐,所以struct Test的自身对齐值为7填充在c之后,struct Test的实际对齐值就是17+7=24。
(2)上述顺序调换
struct Test2                 // 最终大小是自定义大小的整数倍
{
    char c;                    // 1+3
    int a;                       // 4
    double b;                // 8, 这个地方要看上面整体开辟空间是8的倍数字
};
和(1)一样只是把结构体成员的顺序做调换,c这个时候4Bytes,a也是4Bytes,b占8个bytes,整个Test结构体大小必须是8的倍数,现在就是1+3+4+8=16。
(3)更多普通结构体对齐实例
struct Test3                    // 16
{
    double a;                    // 8
    char b;                       // 4
    int c;                          // 4
};

struct Test4             // 3
{
    char a;                // 1
    char b;                // 1
    char c;                // 1
};
同理,Test3里面a占8个字节,b有1+3个字节,c有4个字节,结构体大小对齐8+4+4=16字节,不额外增加对齐值。而Test4中都是char类型,所以Test4大小3Bytes。
(4)我们可以发现在系统默认的存在字节对齐的概念下,让高字节的数据类型放在结构体后面总是能消耗较少的内存空间。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章