POD 类型的填充字节是否被复制?
Do the padding bytes of a POD type get copied?
假设我有一个像这样的 POD 类型:
struct A {
char a;
int b;
};
在我的系统上,sizeof(A) == 8
,即使 sizeof(char) == 1
和 sizeof(b) == 4
。这意味着数据结构有 3 个未使用的字节。
现在假设我们这样做
A x = ...;
A y =x;
问题:
是否保证 x
和 y
的所有 8 个字节都相同,即使是那 3 个未使用的?
等价地,如果我将一些 A
对象的底层字节传输给另一个不理解它们的含义或结构的程序,并将它们视为一个 8 字节的数组,那么另一个程序是否可以安全地比较两个A
平等吗?
注意:In an experiment with gcc 7,这些字节似乎确实被复制了。我想知道这是否有保证。
The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move
of its bases and members.
12.8/15 [class.copy] 在 N4141
因此允许填充字节中的位模式不同。
这不是权威性的,但 cppreference
对 std::memcmp
的条目表明填充字节可能不同:
memcmp()
between two objects of type struct{char c; int n;}
will compare the padding bytes whose values may differ when the values of c
and n
are the same
回答你的第二个问题:
Equivalently, if I transfer the underlying bytes of some A objects to another program that does not understand their meaning or structure, and treats them as an array of 8 bytes, can that other program safely compare two As for equality?
由于您的类型的对象可能包含填充字节,因此另一个程序通常无法比较两个此类对象是否相等:
知道在语义上构成对象的位字节是定义其值表示的关键。然而,在这种情况下,目标程序只知道 object representation,即 bytes 在内存中表示这样一个对象的序列,包括填充字节.像 memcmp 这样的函数只能以有意义的方式比较值表示与其对象表示相同的对象。如果您使用它来按值比较对象,即使它们具有填充,它也可能无法给出正确的结果,因为它无法判断对象表示中的哪些位与两个对象的值表示相等无关。
鉴于您询问了 POD 类型(因此包括联合),值得一提的是 [class.copy]
The implicitly-defined copy/move constructor for a union X copies the object representation (6.9) of X
对于平凡可复制的类型,也应包括填充位。
所以,这可能只是将 A 替换为
的问题
union A{ struct {
char a;
int b;
}; };
(实际上,上面使用了一个非标准的匿名结构,但你明白了……)
假设我有一个像这样的 POD 类型:
struct A {
char a;
int b;
};
在我的系统上,sizeof(A) == 8
,即使 sizeof(char) == 1
和 sizeof(b) == 4
。这意味着数据结构有 3 个未使用的字节。
现在假设我们这样做
A x = ...;
A y =x;
问题:
是否保证 x
和 y
的所有 8 个字节都相同,即使是那 3 个未使用的?
等价地,如果我将一些 A
对象的底层字节传输给另一个不理解它们的含义或结构的程序,并将它们视为一个 8 字节的数组,那么另一个程序是否可以安全地比较两个A
平等吗?
注意:In an experiment with gcc 7,这些字节似乎确实被复制了。我想知道这是否有保证。
The implicitly-defined copy/move constructor for a non-union class X performs a memberwise copy/move of its bases and members.
12.8/15 [class.copy] 在 N4141
因此允许填充字节中的位模式不同。
这不是权威性的,但 cppreference
对 std::memcmp
的条目表明填充字节可能不同:
memcmp()
between two objects of typestruct{char c; int n;}
will compare the padding bytes whose values may differ when the values ofc
andn
are the same
回答你的第二个问题:
Equivalently, if I transfer the underlying bytes of some A objects to another program that does not understand their meaning or structure, and treats them as an array of 8 bytes, can that other program safely compare two As for equality?
由于您的类型的对象可能包含填充字节,因此另一个程序通常无法比较两个此类对象是否相等:
知道在语义上构成对象的位字节是定义其值表示的关键。然而,在这种情况下,目标程序只知道 object representation,即 bytes 在内存中表示这样一个对象的序列,包括填充字节.像 memcmp 这样的函数只能以有意义的方式比较值表示与其对象表示相同的对象。如果您使用它来按值比较对象,即使它们具有填充,它也可能无法给出正确的结果,因为它无法判断对象表示中的哪些位与两个对象的值表示相等无关。
鉴于您询问了 POD 类型(因此包括联合),值得一提的是 [class.copy]
The implicitly-defined copy/move constructor for a union X copies the object representation (6.9) of X
对于平凡可复制的类型,也应包括填充位。 所以,这可能只是将 A 替换为
的问题union A{ struct {
char a;
int b;
}; };
(实际上,上面使用了一个非标准的匿名结构,但你明白了……)