• 有关数据对齐data alignment的很好的解释,做到底层开发比如驱动开发,这些概念很重要


    很多 CPU ,如基于 Alpha, IA-64, MIPS, 和 SuperH 体系的,拒绝读取未对齐数据。当一个程序要求其中之一的 CPU 读取未对齐数据时,这时 CPU 会进入异常处理状态并且通知程序不能继续执行。举个例子,在 ARM, MIPS, 和 SH 硬件平台上,当操作系统被要求存取一个未对齐数据时默认通知应用程序一个异常。

    对齐性
    对齐性是一种内存地址的特性,表现为内存地址模上 2 的幂。例如,内存地址 0x0001103F 模 4 结果为 3 ;这个地址就叫做与 4n + 3 对齐, 4 指出了所选用的 2 的幂的值。内存地址的对齐性取决于所选择的关于 2 的幂值。同样的地址模 8 结果为 7 。

    一个内存地址符合表达式 Xn + 0 ,那么就说该地址对齐于 X 。

    CPU 执行指令就是对存储于内存上的数据进行操作,这些数据在内存上是以地址为标记的。对于地址来说,单独的数据会有其占用内存的字节数。如果它的地址对齐于它 的字节数,那么就称作该数据自然对齐,否则称为未对齐。例如,一个标记 8 字节的浮点数据的地址对齐于 8 ,那么这个数据就自然对齐。

    数据对齐性的编译处理
    设备编译器以一种防止造成数据未对齐的方式来对数据进行地址分配。

    对于单个的数据类型,编译器为其分配的地址是数据类型字节数的倍数。因此,编译器分配给 long 型变量的地址为 4 的倍数,就是说以 2 进制表示地址的话,最后两位为 0 。

    另外,编译器以一种自然对齐每个结构成员的方式来填充结构体。参看下面的代码里面的结构体 struct x_ 。

    Code: Select all
        struct x_
          {
                char a;     // 1 byte
                int b;      // 4 bytes
                short c;    // 2 bytes
                char d;     // 1 byte
          } MyStruct;


    编译器填充这个结构以使其自然对齐。

    例如
    下面的代码说明了编译器是如何在内存中填充的。

    Code: Select all
          // Shows the actual memory layout
          struct x_
         {
               char a;            // 1 byte
               char _pad0[3];     // padding to put 'b' on 4-byte boundary
               int b;            // 4 bytes
               short c;          // 2 bytes
               char d;           // 1 byte
               char _pad1[1];    // padding to make sizeof(x_) multiple of 4
         }


    两种定义在作sizeof(struct x_)运算都会返回12字节。

    第二种定义含有两种填充成分:

    *char _pad0[3]使得int b 在4字节边界上对齐

    *char _pad1[1]使得结构数组struct _x bar[3]对齐。
    填充使得bar[3]各个变量能够自然对齐。

    下面的代码显示了bar[3]的内存结构:

    Code: Select all
                  adr
                  offset   element
    ------   -------
    0x0000   char a;         // bar[0]
    0x0001   char pad0[3];
    0x0004   int b;
    0x0008   short c;
    0x000a   char d;
    0x000b   char _pad1[1];

    0x000c   char a;         // bar[1]
    0x000d   char _pad0[3];
    0x0010   int b;
    0x0014   short c;
    0x0016   char d;
    0x0017   char _pad1[1];

    0x0018   char a;         // bar[2]
    0x0019   char _pad0[3];
    0x001c    int b;
    0x0020   short c;
    0x0022   char d;
    0x0023   char _pad1[1];
  • 相关阅读:
    Swift技术之如何在iOS 8下使用Swift设计一个自定义的输入法 (主要是NSLayoutConstraint 的使用)
    android 旋转手机的时候,如何忽略onCreate再次被系统调用?
    在iOS 8中使用UIAlertController
    09_android入门_采用android-async-http开源项目的GET方式或POST方式实现登陆案例
    一些工具的版本问题 valgrind gdb 以及编译
    C struct __attribute__ ((__packed__))
    C++ class 只允许堆创建/只允许栈创建
    Shell 字符串操作
    存储系统的分类
    ssh 到服务器然后输入中文保存到本地变成乱码
  • 原文地址:https://www.cnblogs.com/super119/p/1996122.html
Copyright © 2020-2023  润新知