结构体成员内存对齐(二)

出处 https://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html

 

结构体在内存中存储位置并不是按照各自的元素占的空间大小顺序放置的,它有一定的规律,这个规律就是结构体成员内存对齐的内容。

需要内存对齐的原因:

1) 平台限制:有些平台智能在特地的位置访问特定类型的数据

2)提高存储数据的速度。有些平台每次都是从偶地址开始提取数据,对于一个int数据,如果从偶地址开始存储,读取该数据只需要一个读写周期,若是从奇数位开始存储,就需要两个周期读取该变量。

 

先看一下具体实例,然后对着这些实例来看对齐方法和一些基本概念

 

#include<cstdio>

struct node1{
    int a;
    char b;
    short c;
}s1;    //4+1+1+2

struct node2{
    char a;
    int b;
    short c;
}s2;    //1+3+4+2

struct node3{
    int a;
    short b;
    char c;
}s3;    //4+2+1+1

struct node4{
    bool a;
    node1 tmp;
    short b;
}s4; // 1+3+8+2

struct node5{
    bool a;
    node1 s;
    double b;
    int c;
}s5;  // 1+3+8+4+8+4+4

int main(){
    printf("sizeof(s1) = %d\n" , (int)sizeof(s1));
    printf("sizeof(s2) = %d\n" , (int)sizeof(s2));
    printf("sizeof(s3) = %d\n" , (int)sizeof(s3));
    printf("sizeof(s4) = %d\n" , (int)sizeof(s4));
    printf("sizeof(s5) = %d\n" , (int)sizeof(s5));

    return 0;
}

 

+ 对于s1大小:int 型占 4 位,下标是 0~3,char 占 1 位,此时保存的下标是 4,4 是 1 的倍数,所以 char 放在下标为 4 的内存,short 占 2 位,此时的下标是 5,5 不是 2 的倍数,比 5 大的且是 2 的倍数是 6 。所以此时填充 1 个字节,short 从下标位 6 的位置开始存储,占据 6-7 两个字节。编译环境是 linux64 位,所以系统默认的对齐参数是 8,当前结构中最大元素对齐参数为 4,所以取小 4 为最终对齐参数 4 ,当前下标位为 8,可以整除对齐参数 4,无需继续填充,所以 s1 共占据  (4+1+1+2 = 8) 个字节。

+ 对于 s2 来说, char 占下标为 0 的内存,此时下标为 1,int 自身对齐参数是 4, 所以填充 3 个字节,存放的下标是 4~7,short 从 8 开始,占据 8~9,对比系统默认字节 8, 结构体成员最大的对齐参数是 4,所以s2这个结构体的最终对齐参数为 4. 12 是 4 的倍数,所以无需填充。最终该结构体占据的内存空间就是 12.

+ 对于 s3 来说,int 占据 0~3 位,short 占据 4~5,char 占据 6,最终对齐参数是 min(4,8) = 4,所以需要填充 7,一共占据 8 个字节。

+ 对于 s4 来说,a 占据 0 位,node 自身对齐参数为 4 (结构体中最大的成员的自身对齐参数),补足 1~3,占据 4 ~11,short 占据 12 ~ 13,结构体 s4 的自身对齐参数为 4, 补充 14 ~15. 共占据 16 个字节空间。

 

因为内存对齐具体的实现是由编译器实现的,所以不同的平台和编译器对于内存对齐的实现方式会有不一样,但是对齐的基本原则都是一致的:

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

2)结构体变量所占空间大小是对齐参数的整数倍。如有需要则会在最后一个成员末尾填充若干字节以达到整体所占空间是对齐参数的整数倍。

在常见的编辑环境下各种类型变量的自身对齐参数都是自身的长度,唯独在 32 位下环境中的 double 长度是8,而自身对齐参数是 4。

 

除了变量的自身对齐参数外,还有一个对齐参数,就是每个编辑器默认的对齐参数,在vs中可以使用 #pargma back(n) 去设置,如果没用设置,就取系统的默认值。windwos32,取值可以为 1,2,4,8,默认为8,linux32 只能取 1,2,4 默认为 4.

 

参考

https://www.cnblogs.com/dolphin0520/archive/2011/09/17/2179466.html

 

posted @ 2021-04-05 15:56  王清河  阅读(109)  评论(0编辑  收藏  举报