2 questions about struct copy

W

WaterWalk

Hi, I'm haunted by 2 questions about struct copy. Though I searched the
net, but still in confusion.

1. Does struct assignment copies every member including array members?
For example,

struct A
{
int n;
int m[2];
} ;

struct A a = { 1, {2,3}};
struct A b = { 7, {8,9}};

After b = a; will b.m[0] and b.m[1] have the same value as in a? I
tested this using mingw, and the answer is yes. But i want to know if
this behavior is guaranteed by standard.

2. Does struct assignment equal to memcpy them?

If so, then after struct assignment, to apply memcmp on them will
return 0(equal); otherwise memcmp will return non-zero.

Any guidance?
 
R

Richard Heathfield

WaterWalk said:
Hi, I'm haunted by 2 questions about struct copy. Though I searched the
net, but still in confusion.

1. Does struct assignment copies every member including array members?
Yes.

2. Does struct assignment equal to memcpy them?

As far as I can make out, the Standard doesn't say this. We can, however, be
assured that each member is correctly copied. A structure can contain
padding bits or even padding bytes, and I can't see any guarantee that
these would be copied too (although in practice it is very likely that they
would be).
 
K

Keith Thompson

WaterWalk said:
Hi, I'm haunted by 2 questions about struct copy. Though I searched the
net, but still in confusion.

1. Does struct assignment copies every member including array members?
For example,

struct A
{
int n;
int m[2];
} ;

struct A a = { 1, {2,3}};
struct A b = { 7, {8,9}};

After b = a; will b.m[0] and b.m[1] have the same value as in a? I
tested this using mingw, and the answer is yes. But i want to know if
this behavior is guaranteed by standard.
Yes.

2. Does struct assignment equal to memcpy them?

If so, then after struct assignment, to apply memcmp on them will
return 0(equal); otherwise memcmp will return non-zero.

Most likely it will, but it's not guaranteed. Structures can contain
gaps between members and/or after the last member. Assignment isn't
guaranteed to copy the contents of those gaps. After an assignment, a
member-by-member comparison will succeed, but memcmp() could fail.
(it's probably easier for the implementation to copy the entire
structure than to skip over the gaps. so this isn't likely to occur in
practice).

I *think* this is correct, but I haven't been able to track down a
definitive statement in the standard.
 
G

Guest

Richard said:
WaterWalk said:


Yes.

With the exception of flexible array members in C99.
As far as I can make out, the Standard doesn't say this. We can, however, be
assured that each member is correctly copied. A structure can contain
padding bits or even padding bytes, and I can't see any guarantee that
these would be copied too (although in practice it is very likely that they
would be).

At least one widely used compiler (GCC) does not always copy padding
bytes, so relying on it is a bad idea. A simple program that can show
it:

#include <stdio.h>
#include <string.h>

struct S1 {
int a;
char b;
char c;
};
struct S2 {
int a;
char b;
};
union S {
struct S1 s1;
struct S2 s2;
};

int main() {
union S x = { { 1, 1, 1 } }, y = { { 2, 2, 2 } };
y.s2 = x.s2;
if(memcmp(&x.s2, &y.s2, sizeof(struct S2)) == 0)
puts("memcmp reports x.s2 and y.s2 are equal");
else
puts("memcmp reports x.s2 and y.s2 are different");
}

(Admittedly, it may report they're equal even when padding bytes are
not copied, but when it reports a difference, as it does for me, you
can be sure.)
 
M

Micah Cowan

Richard Heathfield said:
WaterWalk said:


As far as I can make out, the Standard doesn't say this. We can, however, be
assured that each member is correctly copied. A structure can contain
padding bits or even padding bytes, and I can't see any guarantee that
these would be copied too (although in practice it is very likely that they
would be).

In fact, 6.2.6.1#6 guarantees that they may not be.
 
K

Keith Thompson

I'm cross-posting this to comp.std.c.

Micah Cowan said:
Richard Heathfield said:
WaterWalk said: [...]
2. Does struct assignment equal to memcpy them?

As far as I can make out, the Standard doesn't say this. We can,
however, be assured that each member is correctly copied. A
structure can contain padding bits or even padding bytes, and I
can't see any guarantee that these would be copied too (although in
practice it is very likely that they would be).

In fact, 6.2.6.1#6 guarantees that they may not be.

Thanks; I was looking for a statement to that effect, but I didn't
find it myself. (I guess I should check section 6.2, "Concepts", more
often.)

BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. 6.2.6.1p6 says:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.42) The value of a structure or union object is |
never a trap representation, even though the value of a member of |
the structure or union object may be a trap representation. |

(note the change bars), and footnote 42 says:

42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.
 
R

Robin Haigh

Keith Thompson said:
I'm cross-posting this to comp.std.c.

Micah Cowan said:
Richard Heathfield said:
WaterWalk said: [...]
2. Does struct assignment equal to memcpy them?

As far as I can make out, the Standard doesn't say this. We can,
however, be assured that each member is correctly copied. A
structure can contain padding bits or even padding bytes, and I
can't see any guarantee that these would be copied too (although in
practice it is very likely that they would be).

In fact, 6.2.6.1#6 guarantees that they may not be.

Thanks; I was looking for a statement to that effect, but I didn't
find it myself. (I guess I should check section 6.2, "Concepts", more
often.)

BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. 6.2.6.1p6 says:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.42) The value of a structure or union object is |
never a trap representation, even though the value of a member of |
the structure or union object may be a trap representation. |

(note the change bars), and footnote 42 says:

42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.


While on the subject, I'm not clear as to whether the above quote answers a
question I have. The question is: if we have an auto struct, is it required
that all members be initialised before the struct can be copied by
assignment? If not, where does it say so?
 
K

Keith Thompson

Robin Haigh said:
Keith Thompson said:
I'm cross-posting this to comp.std.c. [...]
BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. 6.2.6.1p6 says:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.42) The value of a structure or union object is |
never a trap representation, even though the value of a member of |
the structure or union object may be a trap representation. |

(note the change bars), and footnote 42 says:

42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.

While on the subject, I'm not clear as to whether the above quote answers a
question I have. The question is: if we have an auto struct, is it required
that all members be initialised before the struct can be copied by
assignment? If not, where does it say so?

I think this is covered by the statement that the value of a structure
or union object is never a trap representation. If there are no trap
representations, there should be no problems with assignment.
 
M

Micah Cowan

Keith Thompson said:
Robin Haigh said:
Keith Thompson said:
I'm cross-posting this to comp.std.c. [...]
BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. 6.2.6.1p6 says:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.42) The value of a structure or union object is |
never a trap representation, even though the value of a member of |
the structure or union object may be a trap representation. |

(note the change bars), and footnote 42 says:

42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.

While on the subject, I'm not clear as to whether the above quote answers a
question I have. The question is: if we have an auto struct, is it required
that all members be initialised before the struct can be copied by
assignment? If not, where does it say so?

I think this is covered by the statement that the value of a structure
or union object is never a trap representation. If there are no trap
representations, there should be no problems with assignment.

Except that the above text says that the value of a /member/ of the
structure or union object may be a trap representation. It will have
been read in the assignment, I should think.
 
S

S.Tobias

In comp.lang.c Keith Thompson said:
BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. 6.2.6.1p6 says:

When a value is stored in an object of structure or union type,
including in a member object, the bytes of the object
representation that correspond to any padding bytes take
unspecified values.42) The value of a structure or union object is |
never a trap representation, even though the value of a member of |
the structure or union object may be a trap representation. |

(note the change bars), and footnote 42 says:

42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.
Why does it matter if it says "bits" or "bytes"? "Padding bytes" are
composed of "padding bits" anyway.

Perhaps the footnote is more general than the part it refers to, and
it means to include padding bits in sub-objects as well (including
bit-field units).
 
K

Keith Thompson

S.Tobias said:
Why does it matter if it says "bits" or "bytes"? "Padding bytes" are
composed of "padding bits" anyway.

No, they're two different things. Padding byte are gaps between
members in a structure, or after the last member of a structure or
union. Padding bits exist only for integer types, and they're
*within* the representation of the integer (and therefore cannot be
padding bytes of an enclosing structure).
 
J

Jordan Abel

No, they're two different things. Padding byte are gaps between
members in a structure, or after the last member of a structure or
union. Padding bits exist only for integer types, and they're
*within* the representation of the integer (and therefore cannot be
padding bytes of an enclosing structure).

Has anyone claimed that pointers can't contain padding bits? Or
floating-point types?
 
R

Richard Heathfield

Robin Haigh said:
While on the subject, I'm not clear as to whether the above quote answers
a
question I have. The question is: if we have an auto struct, is it
required that all members be initialised before the struct can be copied
by
assignment? If not, where does it say so?

Definition of undefined behaviour, in 1.6 (Definitions of Terms):

* Undefined behavior --- behavior, upon use of a nonportable or
erroneous program construct, of erroneous data, or of
indeterminately-valued objects, for which the Standard imposes no
requirements.

Note, in the following code fragment, that a partial initialiser is used:

#include <time.h>
int context(void)
{
struct tm foo = {0};

....and therefore the default static initialiser rule comes into play,
assuring us that all members of the struct are initialised. A useful thing
to know.
 
K

Keith Thompson

Micah Cowan said:
Except that the above text says that the value of a /member/ of the
structure or union object may be a trap representation. It will have
been read in the assignment, I should think.

Not necessarily. Structure assignment *may* be done as if by calling
memcpy(), i.e., copying the raw bytes; this would avoid any problems
from members with trap representation. I *think* that structure
assignment *must* be done this way, or in some equivalent manner
(except that padding bytes needn't be copied).

It's common for some structure members to be meaningless depending on
the values of other members. For example:

#include <stddef.h>
int main(void)
{
#define MAX_LEN 42
struct foo {
int len;
void *ptrs[MAX_LEN];
};

struct foo obj1, obj2;
obj1.len = 1;
obj1.ptrs[0] = NULL;

obj2 = obj1;
return 0;
}

Allowing structure assignment to be affected by member trap
representations would cause the assignment to invoke undefined
behavior.
 
K

Keith Thompson

Jordan Abel said:
Has anyone claimed that pointers can't contain padding bits? Or
floating-point types?

If nobody has, I'll do so now.

The phrase "padding bits" appears in the C99 standard only in 6.2.6.2
(Integer types), 7.18.1.1 (Exact-width integer types), and the index.
Pointers and floating-point types may contain bits that don't
contribute to their values, but the standard doesn't refer to these as
"padding bits".

On the other hand, the phrase "padding bits" doesn't appear in
italics, so it's not a defined term. If you want to call any unused
bits in a pointer or floating-point representation "padding bits", I
suppose the standard doesn't contract that usage.
 
M

Micah Cowan

Keith Thompson said:
Not necessarily. Structure assignment *may* be done as if by calling
memcpy(), i.e., copying the raw bytes; this would avoid any problems
from members with trap representation. I *think* that structure
assignment *must* be done this way, or in some equivalent manner
(except that padding bytes needn't be copied).

Right. I thought about adding the disclaimer that it /might/ not be
"read" by an lvalue other than character type... but since that's
implementation-defined, then it's still implementation-defined whether
it's UB. :)
It's common for some structure members to be meaningless depending on
the values of other members. For example:

#include <stddef.h>
int main(void)
{
#define MAX_LEN 42
struct foo {
int len;
void *ptrs[MAX_LEN];
};

struct foo obj1, obj2;
obj1.len = 1;
obj1.ptrs[0] = NULL;

obj2 = obj1;
return 0;
}

Allowing structure assignment to be affected by member trap
representations would cause the assignment to invoke undefined
behavior.

Good point. Although AFAICT from reading the standard, such may well
be the case. But since this is cross-posted to csc, perhaps we'll hear
from someone who knows more about this.
 
C

CBFalconer

WaterWalk said:
Hi, I'm haunted by 2 questions about struct copy. Though I
searched the net, but still in confusion.

1. Does struct assignment copies every member including array
members? For example,

struct A
{
int n;
int m[2];
} ;

struct A a = { 1, {2,3}};
struct A b = { 7, {8,9}};

After b = a; will b.m[0] and b.m[1] have the same value as in a?
I tested this using mingw, and the answer is yes. But i want to
know if this behavior is guaranteed by standard.
Yes.


2. Does struct assignment equal to memcpy them?

It may, but need not.
If so, then after struct assignment, to apply memcmp on them
will return 0(equal); otherwise memcmp will return non-zero.

structs can have padding areas. They don't affect the content of
the struct. memcmp will consider them, and thus return faulty
results.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
L

lawrence.jones

In comp.std.c Keith Thompson said:
BTW, in n1124.pdf, which incorporates C99 plus TC1 and TC2, there's a
small error in a footnote. [...]
42) Thus, for example, structure assignment need not copy any |
padding bits. |

This should be padding *bytes*, not padding *bits*.

That text was accurately copied from the response to DR #222. I believe
that "bits" was used intentionally so as to include padding bits due to
bit fields and padding bits within members as well as padding bytes
between members.

-Larry Jones

Somebody's always running my life. I never get to do what I want to do.
-- Calvin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,274
Latest member
JessMcMast

Latest Threads

Top