zoukankan      html  css  js  c++  java
  • C结构体的内存对齐

    术语说明

    pack 可以指定内存对齐值,单位是字节,这个是值需要时2的次幂(1,2,4,6,8)。如不设置也有默认值,这个值我理解的是操作系统的字长。

    #pragma pack(8)
    

    对齐规则

    1. 结构体第一个成员放在struct offset 0 的位置。
    2. 计算每个成员的对齐值,计算方式:min(size(成员), 默认对齐值)。
    3. 计算总体的对齐值,计算方式:min(max(所有成员的大小), 默认对齐值)。

    详解

    上面的说明较为笼统,下面使用一个例子来解释。

    # include <stdio.h>
    # pragma pack(8)     # 手动设置对齐值。如不手动设置这个值,不同环境这个值不同,不方面我们接下来的计算。
    
    struct Tag1 {
        double a;
        int b;
        char c;
    };
    
    
    1. 首先将double类型的a,存放在Tag1结构体offset=0的地址上,double类型长度是8,更新offset是8.
    2. 计算int b变量的对齐值,min(size(int), 默认对齐值) = min(4, 8) = 4, 然后判断offset是4的正整数倍数,显然是。将b变量放置在9的位置,此时offset变更成12.
    3. 计算char c变量的对齐值,min(size(char), 默认对齐值) = 1, 然后判断offset是不是4的整数倍呢?12是1的正整数倍,将c变量放置在13位置。
    4. 最后,计算总的对齐值,min(max(double、int、char), 默认对齐值) = min(8, 8) = 8, 13不是8的正整数倍数,填充到16。
    5. 最终 C语言的sizeof(struct Tag1) 的最终值是 16.

    接下来将double 与 int的顺序修改下

    # include <stdio.h>
    # pragma pack(8)     # 手动设置对齐值。如不手动设置这个值,不同环境这个值不同,不方面我们接下来的计算。
    
    struct Tag1 {
        int b;      
        double a;
        char c;
    };
    
    
    1. 首先将int类型b,放在Tag1结构体offset=0的地址上,更新offset=4.
    2. 接下来计算变量double a的对齐值,min(8, 8) = 8, 判断offset=4不是8的整数倍,填充到16(为什么是16?因为需要是8的最小正整数倍),此时offset=16。
    3. 接下来计算变量char c的对齐值,min(1, 8) = 1, 判断offset=16是1的整数倍,将c变量放在17的位置。
    4. 最后计算总的对齐值,min(max(int、double、char), 默认对齐值) = min(8, 8) = 8, 17不是8的正数倍,填充到24.
    5. 最终 sizeof(struct Tag1) 的值是 24.

    嵌套的结构体的对齐

    主要流程差不多,把内部的结构体当作一个变量,先计算这个变量的sizeof。

    注意点

    1. 在一些网络通讯中,如果主机A发送一个结构体的数据到主机B,此时对数据流进行类型转换,可能会出现问题。解决办法是主机A、主机B都设置 # pragma pack(1) .
  • 相关阅读:
    python3
    hive与hbase集成
    spark读取hbase形成RDD,存入hive或者spark_sql分析
    spark机器学习笔记01
    CodeForces 55D Beautiful numbers
    NOIP 2016 D2T2 蚯蚓](思维)
    SCOI 2009 围豆豆(状压DP)
    POJ 1852 Ants(贪心)
    STA树的深度(树型DP)
    HDU 5963 朋友 (找规律,思维)
  • 原文地址:https://www.cnblogs.com/ruiqingliang/p/14471039.html
Copyright © 2011-2022 走看看