【问题标题】:Understanding alignment concept理解对齐概念
【发布时间】:2014-07-15 18:26:26
【问题描述】:

对齐是实现定义的整数值,表示 给定的连续地址之间的字节数 可以分配对象。

这个概念有点不清楚。例如:

struct B { long double d; };
struct D : virtual B { char c; }

当D是一个完整对象的类型时,它会有一个子对象 类型 B,因此它必须与 long double 适当对齐。

这是什么意思? sizeof(long double) 在这种情况下是什么之间的字节数??

【问题讨论】:

  • 对齐这个概念你清楚吗?
  • @KarolyHorvath 不,很难想象。你能举个例子吗?

标签: c++ memory-alignment


【解决方案1】:

大多数 CPU 都有关于数据存储位置的“偏好”。在读取或写入内存地址时,如果地址与您尝试写入的数据大小不匹配,则操作可能会更慢(或完全非法)。例如,通常要求从可被 4 整除的地址开始分配 4 字节整数。

也就是说,存储在地址7 上的int 效率较低或完全非法,具体取决于您的CPU。但是如果存储在地址8,CPU就高兴了。

这就是对齐所表达的意思:对于T 类型的任何对象,它的地址必须能被什么整除才能满足 CPU 的要求?"

在 C++ 中,对象的对齐方式是由实现定义的(因为如上所述,它取决于 CPU 架构)。 C++ 只是说每个对象都有对齐,并描述了如何确定复合对象的对齐方式。

“与long double 对齐”仅意味着必须分配对象,以便将其第一个字节放置在对long double 有效的地址中。如果 CPU 架构将long double 的对齐方式指定为 10(例如),那么这意味着具有此对齐方式的每个对象都必须分配在可被 10 整除的地址上。

【讨论】:

  • 一个含义是填充的概念。示例:“struct A {char c; long double d};”。 long double 字段仍将具有 long double 对齐方式——这意味着 c 和 d 之间将有未使用的间隔。
  • 但是如果在某些架构中 sizeof(char) 不除 sizeof(long double) 呢?
  • @St.Antario sizeof(char) 根据定义为 1,因此架构不存在。
  • @St.Antario 此外,填充(“未使用的空格”)的大小不需要与任何现有类型的大小相对应。它只需要足以使下一个字段正确对齐。从我的 struct A 示例中,假设 sizeof(long double)==10(odd figure,但这是一个示例)。填充将是 9 个字节 (sizeof(long double)-sizeof(char))。
  • @St.Antario C++ 标准确实提供了一些额外的保证:一个对象的大小保证是它的对齐的倍数。 (所以一个8字节的double不能有3的对齐)并且sizeof(char)保证为1。它也保证了在分配对象时,无论是使用new还是在堆栈上,它们都被放置在良好的位置——对齐的地址。对于复合对象,这也意味着编译器可能必须插入填充,以确保每个成员对象都正确对齐,并确保完整对象的大小是最对齐成员的倍数。
【解决方案2】:

我完全理解你的不确定性。这可能是我见过的最糟糕的解释对齐方式的尝试之一。

实际考虑一下。

00100000  64 65 66 61 75 6c 74 0a  31 0a 31 0a 31 0a 31 0a  |default.1.1.1.1.|
00100010  32 0a 31 0a 33 0a 30 0a  31 0a 34 0a 32 33 0a 31  |2.1.3.0.1.4.23.1|
00100020  39 0a 31 37 0a 35 0a 32  36 0a 32 34 0a 33 0a 38  |9.17.5.26.24.3.8|
00100030  0a 31 32 0a 31 31 0a 31  30 0a 31 34 0a 31 33 0a  |.12.11.10.14.13.|
00100040  38 32 0a 38 33 0a 38 34  0a                       |82.83.84.|

这是任意数据的十六进制转储。假设这个数据已经被加载到内存中的地址,如图所示。由于地址是用十六进制写的,所以很容易看出位对齐。

0x100000 和 0x100001 处的数据可以作为 16 位对齐值访问(使用合适的 CPU 指令或通过 C 指针引用访问 16 位数据)。但是数据 0x100003 和 0x100004 没有对齐——它跨越 2 和 3 处的 16 位字,以及 4 和 5 处的 16 位字。前者是 16 位对齐的,而后者不是。

同样,0x100030..100037 处的 64 位(8 字节)值是 64 位对齐的。但是直到 0x100038 之前的一切都不是。

对齐特性是由于内存总线硬件将内存访问组织成总线周期。 16 位数据总线能够在一次操作中获取 8 位或 16 位,但后者仅在地址为偶数时(最低有效地址位为零)。允许“奇数对齐”的 CPU 执行两个连续的总线周期(一个偶数另一个奇数)来完成操作。其他 CPU 只是针对未对齐的总线周期发出故障。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-07
    相关资源
    最近更新 更多