【问题标题】:Class Alignment issue类对齐问题
【发布时间】:2015-01-29 16:14:38
【问题描述】:

我正在测试类对齐并发现奇怪的行为。我使用 VS2012 编译器设置 48 字节对齐设置对其进行了测试,但在每种情况下输出都是相同的。

class Alignemnt{
public:
    Alignemnt():a(){}
    int a;
};

class Alignemnt_1{
public:
    int a;
    char array[2];
};

class Alignemnt_2{
public:
    int a;
    char array[2];
    int x;
};

std::cout <<  "Sizeof(Alignemnt)   :" <<sizeof(Alignemnt) << std::endl;
std::cout <<  "Sizeof(Alignemnt_1) :" <<sizeof(Alignemnt_1) << std::endl;
std::cout <<  "Sizeof(Alignemnt_2) :" <<sizeof(Alignemnt_2) << std::endl;

每次输出为:

Sizeof(Alignemnt)   : 4

Sizeof(Alignemnt_1) : 8

Sizeof(Alignemnt_2) : 12

我认为,Alignemnt_2 的大小应该是 16 字节。

【问题讨论】:

  • 那么,您的问题是什么?在我看来,编译器做得很好?
  • 我认为,Alignemnt_2 的大小应该是 16 字节。
  • int 通常是 4 字节对齐的。 char[2] 只是一个 2 字节的对象。你得到一个 12 字节的大小,因为第一个 int 占用 4 个字节,第二个对象占用 2 个字节,第三个需要 4 个字节对齐。
  • @TonyD 大小是对齐的倍数,因此对齐会影响大小。这甚至没有讨论 member 对齐对包含对象的大小的影响。
  • 也许他应该尝试编译更多测试!经过一些简单的阅读,我在想,也许 Visual Studio 编译器以一种特殊的方式优化了数据存储?

标签: c++ memory-alignment


【解决方案1】:

我假设您指的是/Zp 开关,它可以让您控制最大 结构成员对齐:

当您指定此选项时,第一个结构成员之后的每个结构成员都存储在成员类型的大小或 n 字节边界(其中 n 为 1、2、4、8 或 16)上,以较小者为准。

由于您没有使用对齐超过 4 个字节的结构成员(sizeof(int)alignof(int) 都是 4),所有 4 个字节及以上的设置都将导致完全相同的行为。

如果要指定结构成员的精确对齐方式,请考虑使用标准 C++ alignas,它允许您指定成员应该具有的精确对齐方式(VS 2012 应该支持iirc)。

See the result of using alignas.

【讨论】:

    【解决方案2】:

    对齐不应该改变你的对象的大小,只是对象的起始地址。例如,一个 8 字节对齐的对象可能位于地址 0x100000 或 0x100008,或者以 0x100004 而非 0x100004 为十六进制写入的任何以 0 或 8 结尾的地址。

    【讨论】:

    • 我不同意。对齐与改变对象大小的填充有关。
    • 此外,对象的大小将是其对齐方式的倍数。
    • 是的。 @gha..st。对齐总是使对象的大小成为设置的倍数。这里我把它设为 8 字节,所以应该是 16 而不是 12。
    • 大小不受对齐方式的影响。打包的效率受对齐的影响,但存储对象所需的字节则不受。例如,如果我将一个需要 8 字节对齐的对象与无关紧要的对象打包在一起,则不需要填充。
    • @Charlie 除非您谈论的是过度对齐的类型,否则请查看this example,它确实做到了这一点:将一个 8 字节对齐和大小的对象与一个具有 1 字节对齐和大小的对象打包在一起。更改第一个成员的对齐方式时,大小从 9 个字节变为 16 个字节。
    【解决方案3】:

    没有。

    对齐 2 很好。

    您有 2 个彼此相邻的字符,这意味着您使用了 4 个字节中的 2 个。打包会将其对齐为 4 个字节,然后您将得到 4 + 4 +4 。

    如果您想最终达到 16 个,可以尝试以下声明:

     {
          char a;
          int b;
          char c;
          int d;
     }
    

    【讨论】:

    • @CrazyC 否决票的任何理由?有什么我说的不正确吗?或者你只是为了不赞成投票而反对投票?
    • @CrazyC 啊,对不起。我以为你投了反对票。但是,我仍然想知道为什么投反对票的人投反对票......
    猜你喜欢
    • 2013-01-07
    • 2018-10-28
    • 2011-11-12
    • 2011-05-06
    • 2011-04-22
    • 2012-10-22
    • 2011-01-09
    • 1970-01-01
    相关资源
    最近更新 更多