zoukankan      html  css  js  c++  java
  • 结构体、位域、栈的字节对齐

    为什么要字节对齐

    可移植性:不是所有硬件都能从任意地址开始访问数据,如 MIPS 遇到未对齐内存直接报错
    效率:CPU 每次读取内存时是一块一块读取的,如果目标数据跨越了两个块,CPU 要把两个块都读进来,去掉无关字节,然后将两个块中的目标数据拼接起来,大大降低了 CPU 的效率


    结构体/联合体中的字节对齐

    结构体内的第一个成员的偏移量为0,此后每个成员的偏移量为 min(#pargma pack(),成员自身长度)的倍数
    对于联合体,每个成员的偏移地址都是0

    如果结构体中嵌套结构体/联合体,那么嵌套的结构体/联合体的偏移量必须是它最大成员的字节数的整数倍

    最后,结构体/联合体总的字节数必须是最宽基本类型成员所占字节数的整数倍(包括嵌套的结构体中的基本成员)

    struct outer {
        int a;
        struct {
        	double d;
            char c;
            int i;
        }in;
    };
    //sizeof(struct outer) == 24  sizeof(struct inner) == 16
    
    struct outer {
        int a;
        union inner{
        	double d;
            char c;
            int i;
        }s;
    };
    //sizeof(struct outer) == 16  sizeof(union inner) == 8
    
    union outer {
        int a;
        union inner{
        	double d;
            char c;
            int i;
        }s;
    };
    //sizeof(union outer) == 8  sizeof(union inner) == 8
    

    位域的压缩与字节对齐

    首先简单介绍一下位域(bit filed、位段)
    位域用于声明将数据以位的形式紧凑储存,并允许直接对位域变量进行操作
    位域类型变量不可取址
    优点:①节省空间;②可以方便将一个整数值的部分位作为整体访问、操作
    缺点:位域的压缩与对齐是平台、机器相关的,难以移植

    位域的压缩:

    • 如果相邻位域字段的位域类型相同,各个字段只占定义时的位长度
    • 如果一个位域字段的长度压缩时会跨越两个位域类型存储单元,则对齐到第二个单元存储
    • 如果位域字段间有非位域字段,则这两个位域字段不进行压缩

    位域的对齐:如果相邻的位域字段类型不同,则按照结构体对齐规则对位域类型进行对齐

    位域就像,按位域类型正常分配空间,压缩性地使用部分空间

    struct test{
        char c1:1;
        char c2:2;
        char c3:7;
        int  i:3;
        char c4:2;
    };
    //sizeof(struct test) == 12, c3从第二个字节开始, i从第五个字节开始, c4从第九个字节开始
    

    调用栈的字节对齐

    主要是为了支持 SSE(Streaming SIMD Extensions)浮点运算扩展指令集与16字节的 XMM 浮点寄存器
    GCC 栈帧的边界默认以16字节对齐,栈帧内按正常规则对齐


    编译器对字节对齐的支持

    对于 VC 来说,有 #pargma pack(n) 预处理命令,如 #pargma pack(8),指定按照8字节对齐
    #pargma pack(push) 、#pargma pack(pop) 保存当前字节对齐状态、弹出栈顶字节对齐状态
    #pragma pack (),取消自定义字节对齐方式


    对于GCC,除了 #pargma pack(n) 预处理命令外
    还可以使用 __attribute__ 机制来指定字节对齐数,如在描述GDT表项的数据结构中,

    struct gdt_entry {
        uint16_t limit_low;
        uint16_t base_low;
        uint8_t base_middle;
        uint8_t access;
        unsigned limit_high: 4;
        unsigned flags: 4;
        uint8_t base_high;
    } __attribute__((packed));
    

    attribute 中 packed 表明 struct / union 中的成员紧紧地打包在一起,不进行字节对齐(亲测 DEVC gcc,还是进行了对齐)
    可以使用 aligned (alignment) 属性来指定字节对齐数
    如 __attribute__((aligned(4))) 四字节对齐,__attribute__((aligned)) 默认对齐方式

    此外,attribute 属性的效果与链接器也有关,attribute 属性指定的字节对齐数,需要链接器也支持


    2019/12/22

  • 相关阅读:
    可伸缩性/可扩展性(Scalable/scalability)
    广播变量与累加器
    swool配置ssl
    使用smb映射到本地时 访问权限,请联系管理员错误
    npm 安装cnpm淘宝镜像时报错解决
    在使用mysql8.0的时候遇到的密码链接问题
    配置ubuntu的超管账号密码
    nginx 配置laravel框架域名配置
    eclipse 下载安装单元测试log4j的配置与搭建
    eclipse安装Spring的具体步骤
  • 原文地址:https://www.cnblogs.com/kafm/p/12721788.html
Copyright © 2011-2022 走看看