Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么编译器会抱怨对齐?_C++_Visual C++_Compiler Construction_Alignment_Compiler Warnings - Fatal编程技术网

C++ 为什么编译器会抱怨对齐?

C++ 为什么编译器会抱怨对齐?,c++,visual-c++,compiler-construction,alignment,compiler-warnings,C++,Visual C++,Compiler Construction,Alignment,Compiler Warnings,我想了解更多关于对齐的信息。为什么Microsoft编译器(Visual Studio 2012 Express)抱怨以下代码片段的对齐方式 __declspec(align(16)) class Foo { public: virtual ~Foo() {} virtual void bar() = 0; }; 这是编译器向我发出的警告: warning C4324: 'Foo' : structure was padded due to __declspec(align()

我想了解更多关于对齐的信息。为什么Microsoft编译器(Visual Studio 2012 Express)抱怨以下代码片段的对齐方式

__declspec(align(16)) class Foo
{
public:
    virtual ~Foo() {}
    virtual void bar() = 0;
};
这是编译器向我发出的警告:

warning C4324: 'Foo' : structure was padded due to __declspec(align())

这个类是否有任何虚方法都无关紧要。即使对于空类,编译器也会发出相同的警告消息。空类是如何对齐的?编译器如何填充这个类?

在x86 Foo中需要4个字节,因此需要12个字节的填充。在x64中,Foo需要8个字节,因此需要一个8字节的pad。

此警告说明,由于使用
\uu declspec(align())
,类的大小(由
sizeof
返回)已更改(增加)。这可能会破坏事物,因此警告

当然,空类的大小必须大于0,因此它至少为1


通常情况下,大小不会随对齐方式而更改,但在您的情况下会更改,因为您指定的对齐方式大于类的未添加大小。请记住,在C中,类型的对齐不能小于其大小,实际上大小必须是对齐的倍数,因此大小会增加以匹配对齐


为什么尺寸必须是路线的倍数?好吧,想象一下这种类型的数组:连续的元素需要用sizeof(T)精确地分隔,但每个对象必须位于对齐的内存地址倍数中。这个等式的唯一解决方案是
sizeof(T)
必须是对齐的(非空)倍数。

警告不一定意味着你做错了什么,但告诉你你可能不是故意的。请注意,编译器可以对开发人员认为值得警告的任何事情发出警告。原则上,你也可能被警告在13号周五编译

在这种特定情况下,假设在指定对齐方式时,不希望使类变大。因此,如果由于您给出的对齐要求,类变得更大,那么您犯错误的可能性不大

当然,这留下了一个问题,为什么对齐要求会使类变大。现在我们又回到了标准领域(尽管
\uu declspec
本身是微软的扩展,而不是标准)。C++标准要求在数组中,对象之间没有任何空格。因此,如果对象必须与16字节边界对齐,则对象的大小必须是16的倍数。如果成员的大小(显式和隐式)没有提供必要的大小,编译器必须向对象添加未使用的字节。这些字节称为填充。请注意,即使在不是数组成员的对象中也存在这种填充


现在,您的类只包含一个隐式虚拟指针(因为它包含虚拟函数),根据体系结构的不同,该指针可能是4字节或8字节大。由于您请求了16字节对齐,编译器必须添加12或8字节的填充,以使大小达到16的倍数,如果没有手动对齐规范,就不必添加。这就是编译器所警告的。

当您使用
\uuu declspec(align())
alignas()
,它不仅会使您的结构更严格地对齐,而且可能必须在结构的末尾填充,根据以下内容:

结构尺寸是其路线的最小倍数,大于或等于其最后一个构件末端的偏移


换句话说,如果将结构的对齐度增加到16,则最好确保结构的大小也是16的倍数,否则可能会由于填充而使结构的大小发生变化,从而导致程序中断(编译器无法告诉您在多大程度上依赖于结构的大小以及您是否知道此规则,因此它会发出警告).

它的对齐方式与您特别告诉编译器的对齐方式相同,为16字节。这需要16字节的填充。我认为,没有填充的空结构将是1对齐的,大小为1。空类是“特殊的”因为标准要求没有完整对象的大小为0,所以没有数据成员或基的类如果没有vtable,则总是需要一些填充。对齐要求意味着它需要更多。请尝试将警告降低到级别4,而不是“全部”。使用“全部”启用警告后,它会抱怨一切,包括你最喜欢的颜色和你狗的名字。好吧,但这似乎不是自然对齐方式。如果我没有明确告诉编译器以某种方式对齐空类,我想了解空类是如何对齐的。@FairDinkumThinkum:根据定义,类的对齐方式必须是f因此,请参阅它的大小,不要查看<代码> >“yxDeScript(Acthor))< /C> >的空类的大小。如果它是1,则必须是1。C++ 11也有<代码>对齐> <代码>操作符,因此如果你可以从VisualC++中获得这个值,那么它就消除了所有的疑虑。哦,别介意。我收回我的评论(实际上没有删除它)。。您得到的警告与打开
Wall
时通常看到的结构填充警告不同,“因为您指定的对齐方式大于类的未添加大小”这不完全正确。一个有3个字符、对齐为2的对象将获得额外的1字节填充。@MooingDuck:当然,你是对的。我的意思是:“如果所需对齐大于大小,那么大小将增大”(而不是“如果且仅当”).应该有一个警告:你今天早上9点开始,现在是晚上8点。吃些奇怪的食物,你处于低血糖状态,你的密码是胡说八道。回答得很好。谢谢