【问题标题】:How to ensure a member is 4-byte aligned?如何确保成员是 4 字节对齐的?
【发布时间】:2010-01-23 20:06:53
【问题描述】:

为了使用 OSAtomicDecrement(mac 特定的原子操作),我需要提供一个 4 字节对齐的 SInt32。

这种烹饪方法有用吗?还有其他方法可以解决对齐问题吗?

struct SomeClass {
  SomeClass() {
    member_  = &storage_ + ((4 - (&storage_ % 4)) % 4);
    *member_ = 0;
  }

  SInt32 *member_;

  struct {
    SInt32 a;
    SInt32 b;
  } storage_;
};

【问题讨论】:

    标签: c++ atomic memory-alignment


    【解决方案1】:

    如果您使用的是 Mac,那就意味着 GCC。 GCC 可以为您自动对齐变量:

      __attribute__((__aligned__(4))) int32_t member_;
    

    请注意,这不能跨编译器移植,因为这是 GCC 特定的。

    【讨论】:

    • 这个解决方案的好处是什么,因为它不那么便携(并且可以额外使用 4 字节的空间)?
    • -1:这确保指针的存储是对齐的。是的,因为它是对齐的 storage_ 也会对齐,但这是间接且令人困惑的。如果要推荐指定对齐方式,直接对齐变量即可(去掉struct,直接创建成员__attribute__((__aligned(4))) SInt32 a_;
    • 没有“使用额外的 4 个字节”,GCC 只是重新定位类以满足您的需求。也没有办法在编译器之间可靠地做到这一点,MSVC 有这样一个选项(__declspec align?)。您有只有链接器才能满足的特殊需求,并且您认为没有编译器特定的选项就可以逃脱?指针是粘贴代码的遗留物,它不应该存在(已编辑)。
    • @LiraNuna 在我的示例中存在 4 个额外字节,而不是在您的示例中。对困惑感到抱歉。你可能是对的,我可能无法避免编译器依赖...
    • Mac 并不一定意味着 GCC。可以使用 clang/llvm,ICC 支持 OS X,其他一些编译器也是如此。
    【解决方案2】:

    我猜任何 SInt32 都已经对齐,即使在 mac 上也是如此。

    澄清一下:

    struct Foo {
        SInt32 member;
    };
    

    member 总是正确对齐,除非您打包结构并将 member 放在一个字符之后。

    【讨论】:

    • PowerPC 上会出现这种情况,但 x86 上不会。 PPC 是大端 - 单词必须对齐,但在小端上,不能保证这一点。
    • 没有编译器会故意生成在 x86 上使用未对齐访问的代码。这会导致严重的性能损失。
    • @LiraNuna 这不是真的。 Microsoft Visual C++ 和 GCC 保证 int 与 x86 上的 4 字节边界对齐。如果是 Visual C++,它记录在 MSDN 上。
    • 绝对正确。默认情况下,所有 4 字节基本类型在 OS X 上都是 4 字节对齐的。
    【解决方案3】:

    ints 默认情况下与任何 OS X 编译器都是 4 字节对齐的。您需要做的就是不要故意破坏这种对齐方式(例如,通过不正确的指针转换、将您的结构标记为 packed 等)。

    【讨论】:

      【解决方案4】:

      我对 Mac 编程一无所知,但在我曾经使用过的小型计算机上,指针总是在 4 字节(字)边界上对齐。 IIRC,结构也是。分配的内存一直是。

      【讨论】:

        【解决方案5】:

        如果您的编译器支持 TR1(或 C++0x),您可以使用 std::aligned_storage 模板。

        要为大小为S 且对齐为A 的对象分配空间,您可以分配std::aligned_storage<S, A>::storage 类型的对象。

        (命名空间可能因编译器而异。我认为TR1没有指定扩展必须放在哪个命名空间。在MSVC上,使用命名空间std::tr1

        除此之外,编译器已经对 32 位整数进行了 4 字节对齐(至少在 32 位整数的自然对齐为 4 字节的平台上)

        【讨论】:

          【解决方案6】:

          如果你想在结构中强制对齐,你可以使用位域。

          struct 
          {
             Foo _hisFoo;
             unsigned int dummyAlignment : 0;
             Foo _myFoo;
          }
          

          【讨论】:

          • 一个零长度位字段填充到其基本声明类型的下一个对齐边界。这会导致下一个成员从字节边界(对于 char 位字段)、2 字节边界(简称)、4 字节边界(对于 int 或 long)或 8 字节边界(对于 long long)开始。如果前一个成员的内存布局在适当的边界上结束,则不会发生填充。
          猜你喜欢
          • 2020-10-04
          • 1970-01-01
          • 2015-05-28
          • 2013-05-13
          • 2023-03-19
          • 2012-07-18
          • 2017-04-06
          • 2011-10-14
          • 1970-01-01
          相关资源
          最近更新 更多