警告 C4121 行为和结构对齐 (Visual Studio 2010)

Warning C4121 behavior & structure alignment (Visual Studio 2010)

本文关键字:Visual Studio 2010 对齐 结构 C4121 警告      更新时间:2023-10-16

让我们考虑下面的声明。(Visual Studio 2010,警告级别4)

#pragma pack(push, 2)
#define PADDING 1 // --- <case 1>
/*
#define PADDING 2 // --- <case 2>
*/
struct foo
{
    char a[PADDING];
    int b;
};

症状

如果将PADDING设置为<case 1>,它肯定会生成C4121。但对于<case 2>,它可以在没有任何警告的情况下编译。这两种情况具有相同的结构布局,"b"的偏移量为2字节
我预期<case 2>为C4121,因为"b"没有在sizeof(int)边界的倍数上对齐。(来自MSDN。我找不到2010版本。)

问题

我想知道只有<case 1>产生C4121是否合理,因为得到的结构布局(对齐)是相同的
我错过了什么重要的东西吗?我应该忽略C4121吗?

PS

事实上,我在遇到过这种情况

  • 默认对齐值(8字节)
  • 指向未定义(仅向前声明)类(16字节)的成员函数的指针

所以,我认为具体的对齐值并不是重点。我写了上面的示例代码,使事情变得简单。

如果你忽略了这个警告,你必须记住:

当数据不在数据大小倍数的边界上对齐时,性能可能会降低,如果您将代码移植到RISC机器,它将不会编译。

至少,你必须决定是否可以冒险抛出异常。。。

使用#pragma pack()来解决它是一个很好的方法,但有一个问题:

#pragma pack指令只能用于从项目默认打包中减少结构的打包大小。这会导致库头的互操作性问题,例如,如果将项目打包设置为小于此值,则使用#pragma pack(8)。MSDN文档[5]指出,如果#pragma pack打包大于或等于项目打包,它将被忽略。

因此,永远不应该将项目打包设置为默认值8字节以外的任何值,因为这会破坏库头中使用的#pragma-pack指令,并导致结构之间的二进制不兼容

但也包括:

x86体系结构最初不需要对齐的内存访问,在没有它的情况下仍然可以工作

我建议你避免这个警告,这样会更安全。。。

解决这一问题的方法是颠倒struct成员的顺序,如下所示:http://msdn.microsoft.com/en-us/library/kabt0ka3%28v=vs.80%29.aspx

编辑:另一个链接解释了什么是数据结构对齐以及随之而来的问题:https://en.wikipedia.org/wiki/Data_structure_alignment(我建议您阅读定义问题部分)

我认为这可能是编译器的问题:

#pragma pack(push, 2)
struct foo
{
    char a[3];
    int b;
}; 
int main()
{
    foo f[2];
    cout << "sizeof(f) = " << sizeof(f) << endl;
    cout << "&f[0] =" << &f[0] << endl;
    cout << "&f[1] =" << &f[1] << endl;
    cout << "&f[0].b =" << &(f[0].b) << endl;
    cout << "&f[1].b =" << &(f[1].b) << endl;
}

对于1和3,我得到警告,对于2没有,尽管对于1和2,地址是相同的。