Do the padding bytes of a POD type get copied?
Asked Answered
C

4

51

Suppose I have a POD type like this:

struct A {
    char a;
    int b;
};

On my system, sizeof(A) == 8, even though sizeof(char) == 1 and sizeof(b) == 4. This means that the data structure has 3 unused bytes.

Now suppose we do

A x = ...;
A y =x;

Question:

Is it guaranteed that all 8 bytes of x and y will be identical, even those 3 unused ones?

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?

Note: In an experiment with gcc 7, it appears that those bytes do get copied. I would like to know if this is guaranteed.

Cotquean answered 22/10, 2017 at 14:10 Comment(5)
Related: https://mcmap.net/q/265050/-why-does-the-operator-work-on-structs-without-having-been-definedExtrasystole
I don't think the dupe answers the question "are the padding bytes the same". It only says that memcpy copies them, but that's not exactly what OP asked.Volost
@Volost "= is only required to copy the members. It might or might not copy the padding." Second paragraph in the top answer.Subbasement
There is no guarantee that assignment or initialization will copy padding. In some cases it can be critical that it's not copied (padding can be reused in inheritance). memcpy will copy it though, because it doesn't know about it.Ose
If you need to copy the padding bytes as well, you can do so with memcpy(). Another technique I’ve sometimes used in C is to set all the bytes of the structure to 0 with memset(), and then do your memberwise copy. Modern compilers have been able to optimize the redundant double writes away for more than a decade.Headset
S
47

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] in N4141

The bit pattern in the padding bytes is thus allowed to differ.

Subbasement answered 22/10, 2017 at 14:28 Comment(6)
It's kind of unfortunate that N4141 is password protected. It looks like it is the final standard for C++14. A draft of which is N4140, the information is from this Reddit thread. I can't say I trust that reddit thread 100%. In it, it's 12.8/16, not 15. Is there anywhere a directed graph where standards and drafts are nodes and an edge means is part of?Fifty
@StefanHanke Actually, the source of N4141 is available on github, you just have to build it yourself. github.com/cplusplus/draft/tree/n4141Subbasement
"Actually, the source of N4141 is available on github, you just have to build it yourself" That's a very C++ thing to say.Dunnite
Does that mean it can't copy the padding bytes, or that it doesn't have to? (I figured under the as-if rule it could?)Goosy
@Goosy I would not read that from the quote (i.e. I think it can copy).Subbasement
@BaummitAugen Hmm, I was hoping it couldn't... darn!Goosy
T
6

It's not authoritative, but cppreference's entry for std::memcmp suggests that the padding bytes may differ:

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

Trichotomy answered 22/10, 2017 at 14:29 Comment(1)
Not sure what this has to do with copying?Subdivide
J
6

given that you asked about a POD type ( hence including unions ) it's worth mentioning that according to [class.copy]

The implicitly-defined copy/move constructor for a union X copies the object representation (6.9) of X

that for trivially copyable types should include padding bits as well. So, it could be just a matter of replacing A with

union A{ struct {
    char a;
    int b;
}; };

(actually, the above uses a non standard anonymous struct, but you get the point ... )

Jamesjamesian answered 22/10, 2017 at 15:16 Comment(1)
Relevant link: #26241897Filmdom
C
4

Answering your second question:

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?

As an object of your type may contain padding bytes, another program generally can not compare two such objects for equality:

Knowing which bits of the bytes that make out the object semantically is the key for defining its value representation. However, in this scenario, the target program only knows the object representation, i.e. the sequence of bytes representing such an object in memory, including padding bytes. A function like memcmp can only compare such objects whose value representation is identical to its object representation in a meaningful way. If you use it to compare objects value-wise even though they have padding, it may fail to give the right results as it cannot tell which bits in the object representation are irrelevant for the value representations of two objects to be equal.

See http://en.cppreference.com/w/cpp/language/object

Conidium answered 22/10, 2017 at 14:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.