【问题标题】:Do pointer casts maintain alignment properties?指针转换是否保持对齐属性?
【发布时间】:2019-05-22 13:45:30
【问题描述】:

说,我有一个对齐的数组

alignas(X) char arr[sizeof(X)];

是指针

X * ptr = reinterpret_cast<X*>(arr);

保证按照X的对齐要求正确对齐?

情况似乎很明显,但从 C++ 标准来看似乎并不明显。

我在标准中找不到任何会阻止编译器对齐表单结构的内容

struct X
{
    int16_t a;
    int32_t b;
    int16_t c;
};

像这样在记忆中:

+-+-+-+-+-+-+-+-+
|a|a|b|b|b|b|c|c|
+-+-+-+-+-+-+-+-+
     ^
     aligned to 32-boundary

以便X 类型的对象以不需要填充的方式对齐,并且b 同时与 32 位边界正确对齐。声明(N4713,§ 6.6.5.1)

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

没有被违反,我在标准中没有看到任何其他违反它的声明。

【问题讨论】:

  • 我对这个问题感到困惑,但也许我没有正确理解它。您是否在想象X 不包含填充但需要int32_t 进行32 位对齐的场景?您是在问标准的哪一部分阻止了这种情况?
  • 我猜 alignas 是指从结构开始的内存对齐,与结构在内存中的实际位置无关。
  • @FrançoisAndrieux 是的,这正是我要问的。
  • @RalphTandetzky 我不确定标准中是否有明确的段落。它可能从其他语言规则中隐含,例如X x; auto y = &amp;x.b; 需要生成指向b 的可用指针这一事实,可能是语言如何定义运算符地址的定义的一部分。
  • 如果结构的开头已经与 32 位边界对齐(例如来自 mallocnew),b 将如何与 32 位边界对齐。 b 与 32 位对齐(在 8 位字节可寻址系统上)要求结构的开头与一个地址对齐,除以 4 时留下 2。

标签: c++ pointers memory alignment language-lawyer


【解决方案1】:

你的结构应该有一个奇特的对齐方式:它应该是 16 位对齐但不是 32 位对齐。从数学上讲,它的地址应该是 32*n+16 的形式,其中 n 是一个整数。

这是语言所禁止的,32 位对齐应该满足 16 位对齐。换句话说,任何 16 位对齐的结构都应该适合 32 位对齐的存储区域,但您的 16 位对齐结构不适合。见[basic.align]/5

对齐的顺序是从弱到强或更严格的对齐。更严格的对齐具有更大的对齐值。满足对齐要求的地址也满足任何较弱的有效对齐要求。

【讨论】:

    【解决方案2】:

    标准的作者并没有试图明确禁止他们认为不可能的事情。如果一个编译单元包含与您提供的结构类似的结构:

    struct {
      uint16_t a;
      uint32_t b;
      uint16_t c;
    } x;
    

    并且编译器并非全知x 或具有相同布局的结构可能在整个程序的其余部分中使用的所有方式,它别无选择,只能使b 的偏移量成为倍数b 的对齐方式。我不认为标准明确规定结构的布局不会受到使用方式的明显影响,但我认为这是因为他们认为布局可能以这种方式变化的编译器不会能够维护通用初始序列保证。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2017-07-04
      • 1970-01-01
      • 2013-07-11
      • 2018-06-10
      • 2012-02-23
      相关资源
      最近更新 更多