将类型包装在结构中会导致额外的填充吗?

发布于 2024-12-02 14:10:44 字数 417 浏览 2 评论 0原文

可能的重复:
单个元素的结构大小

给定任何类型A 和以下结构:

struct S
{
    A a;
};

是否存在 sizeof(S) 大于 sizeof(A) 的情况?

例如,sizeof(std::array) 可以大于 sizeof(T[n]) 吗?

Possible Duplicate:
Size of struct with a single element

Given any type A and the following struct:

struct S
{
    A a;
};

Are there any cases where sizeof(S) is greater than sizeof(A)?

For example, can sizeof(std::array<T, n>) be greater than sizeof(T[n])?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

痴者 2024-12-09 14:10:44

能够在 S 内部使用 A 意味着编译器已经了解 A 的结构,并且已经向其中添加了填充字节。我认为没有理由为 S 添加进一步的填充,因为它已经对齐了。

Being able to use A inside of S means that the compiler already has knowledge of the structure of A and has already added padding bytes to it. I see no reason for it to add further padding to S, as it already is aligned.

戏舞 2024-12-09 14:10:44

虽然结构可以被填充,但在我知道的所有系统上,编译器都会填充,以便结构的对齐方式与其成员的最大对齐方式相同。这样做是为了使结构数组始终正确对齐。

所以:

struct S 
{
   char a;
} // Size 1, no padding

struct S2 
{
   unsigned int a;
   char b;
} // Size 8, 3 bytes padding (assuming 32 bit integer)

编辑:注意,编译器还可以添加内部填充,以保持数据的对齐正确。

C/C++ 标准没有指定任何这些细节。您想要的是您正在运行的系统的 C ABI(应用程序二进制接口),它应该指定结构的默认布局(编译器可以选择覆盖它,如果他们认为合适,另请参阅#pragma pack)。例如,请查看 X86_64 ABI 第 13 页,其中指出:

聚合和联合结构和联合假设对齐
它们最严格对齐的组件。每个成员被分配到
适当对齐的最低可用偏移。尺寸
任何对象的对齐方式始终是对象对齐方式的倍数。一个数组
使用与其元素相同的对齐方式,除了本地或全局
长度至少为 16 个字节的数组变量或 C99 可变长度
数组变量始终具有至少 16 个字节的对齐方式。结构
联合对象可能需要填充以满足大小和对齐的要求
限制。任何填充的内容都是未定义的。

While the struct can be padded, on all systems I know, the compiler will pad so that the alignment of the structure is the same as the largest alignment of its members. It does this so that an array of the structure will always be correctly aligned.

So:

struct S 
{
   char a;
} // Size 1, no padding

struct S2 
{
   unsigned int a;
   char b;
} // Size 8, 3 bytes padding (assuming 32 bit integer)

Edit: Note, that compilers can also add internal padding, to keep the alignment of the data correct.

The C/C++ standard doesn't specify any of these detail. What you want is the C ABI (application binary interface) for the system you're running on, which should specify default layout for structs (compilers can choose to override this if they see fit, see also #pragma pack). For an example, look at the X86_64 ABI page 13, which states:

Aggregates and Unions Structures and unions assume the alignment of
their most strictly aligned compo- nent. Each member is assigned to
the lowest available offset with the appropriate alignment. The size
of any object is always a multiple of the object‘s alignment. An array
uses the same alignment as its elements, except that a local or global
array variable of length at least 16 bytes or a C99 variable-length
array variable always has alignment of at least 16 bytes. Structure
and union objects can require padding to meet size and alignment
constraints. The contents of any padding is undefined.

贪恋 2024-12-09 14:10:44

相关文本是 5.3.3/2“当应用于类时,结果是该类的对象中的字节数,包括将该类型的对象放入数组中所需的任何填充。”

出于数组边界检查的目的,实现可以添加额外的字节(例如“这是总共 12 个数组成员中的第 5 个”,因为这是在此处授予的余地内且未明确指定) (据

推测,该实现还会为不属于数组的结构存储“1 of 1”指示;在 C++ 中,类型 SS [1] 是相当可互换)

The relevant text is 5.3.3/2 "When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array."

An implementation is allowed to add extra bytes for the purposes of array bound checks (e.g. "this is the 5th array member out of a total of 12", as this is within the leeway granted here and not explicitly banned by any other requirement.

(Presumably, that implementation would also store a "1 out of 1" indication for structs that aren't part of an array; in C++ the types S and S[1] are quite interchangable)

沉溺在你眼里的海 2024-12-09 14:10:44

ISO/IEC 14882(10/2008) 1.8.5

除非它是位字段(9.6),否则最派生的对象应具有非零大小,并应占用一个或多个
字节存储。基类子对象的大小可能为零。

这意味着结构的大小为1,尽管“所有数据成员”(没有)的大小为零,零长度位字段也是如此(根据9.6.2,这将是不过,必须是未命名位字段)。
但这两种情况都没有真正适用,因为您没有要求一个空结构,并且您的成员已命名(因此它不能是零长度)。

如果您的 a 成员的类型为 void,情况也是如此,但 3.9.5 不允许这样做("[.. .] void 类型是不完整类型(3.9.1)。对象不应被定义为具有不完整类型”)。

简而言之,正如您所说,您最感兴趣的是标准的内容:不,标准没有明确定义这种情况。

但是,它也不禁止编译器添加填充或应用对齐,并且大多数编译器默认情况下会根据机器字大小填充/对齐结构(除非另有明确说明)。

ISO/IEC 14882(10/2008) 1.8.5:

Unless it is a bit-field (9.6), a most derived object shall have a non-zero size and shall occupy one or more
bytes of storage. Base class subobjects may have zero size.

This means that an empty struct has a size of 1 although the size of "all data members" (there are none) is zero, as would a zero-length bitfield (according to 9.6.2 this would have to be an unnamed bitfield, though).
Neither really applies though, as you did not ask for an empty struct, and your member is named (so it can't be zero-length).

Similar would be true if your a member was of type void, but 3.9.5 does not allow that ("[...] the void types are incomplete types (3.9.1). Objects shall not be defined to have an incomplete type").

So in short, as you said you are mostly interested about what the standard says: no, the standard does not explicitly define such a case.

However, it also does not forbid the compiler to add padding or apply alignment, and most compilers will pad/align structures to machine word size by default (unless explicitly told otherwise).

笑红尘 2024-12-09 14:10:44

结构可以被填充(编译器可以做任何他们喜欢的事情,例如将六个八位字节类型填充到八个八位字节以与页面边界对齐)。但这不太可能发生。

std::array 将会更大,因为它在类中存储了一些额外的信息,例如数组的长度。 自动驾驶;不假思索地阅读 std::vector 。

A struct can be padded (it's allowed for compilers do whatever they like, for example padding a six-octet type to eight to align with page boundaries). It's unlikely to happen though.

std::array will be bigger, because it stores some extra information in the class, like the array's length. Typing on auto-pilot; read std::vector without thinking.

半窗疏影 2024-12-09 14:10:44

如果 A 是一个字节,则结构将与最近的边界对齐。相反,如果 A 小于边界,那么它会更大。 EX RGB 结构与 RGBA 结构大小相同。

我没有可以做到这一点的示例代码。您必须转储内存并查看漏洞。如果您假设所有内容都大小对齐并将结构投射到一叠内存上,那么您将得到错误的数据。这就是 WAD 具有用于对齐的填充的原因。随着您的组合变得更加复杂,编译器弥补漏洞的能力就会减弱。最终将引入填充,并且任何内存布局的假设都将变得越来越错误。

If A is a byte then struct will align to the nearest boundary. Rather if A is smaller than a boundary then yes it will be bigger. EX a struct of RGB is the same size as a struct of RGBA.

I don't have sample code that will do that. You have to dump memory and see the holes. If you then assume that everything is size aligned and cast a structure onto a wad of memory you will have bad data. This is why WADs had padding for alignment. As your compositions get more complicated, the ability to close holes by the compiler is diminished. Eventually padding will be introduced and any assumptions of memory layout will become more and more wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文