By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,687 Members | 2,046 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,687 IT Pros & Developers. It's quick & easy.

2 questions about struct copy

P: n/a
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?

Mar 3 '06 #1
Share this Question
Share on Google+
28 Replies


P: n/a
Here http://www.le.ac.uk/cc/tutorials/c/ccccstrc.html is a good source
about struct copying.

Mar 3 '06 #2

P: n/a
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).

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Mar 3 '06 #3

P: n/a
"WaterWalk" <to********@163.com> writes:
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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #4

P: n/a
Richard Heathfield wrote:
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.


With the exception of flexible array members in C99.
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).


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.)

Mar 3 '06 #5

P: n/a
Richard Heathfield <in*****@invalid.invalid> writes:
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).


In fact, 6.2.6.1#6 guarantees that they may not be.
Mar 3 '06 #6

P: n/a
I'm cross-posting this to comp.std.c.

Micah Cowan <mi***@cowan.name> writes:
Richard Heathfield <in*****@invalid.invalid> writes:
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*.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #7

P: n/a

"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
I'm cross-posting this to comp.std.c.

Micah Cowan <mi***@cowan.name> writes:
Richard Heathfield <in*****@invalid.invalid> writes:
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?

--
RSH

Mar 3 '06 #8

P: n/a
"Robin Haigh" <ec*****@leeds.ac.uk> writes:
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #9

P: n/a
Keith Thompson <ks***@mib.org> writes:
"Robin Haigh" <ec*****@leeds.ac.uk> writes:
"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
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.
Mar 3 '06 #10

P: n/a
Micah Cowan said:
Richard Heathfield <in*****@invalid.invalid> writes:
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.


That's a definite maybe! :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Mar 3 '06 #11

P: n/a
In comp.lang.c Keith Thompson <ks***@mib.org> wrote:

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).

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Mar 3 '06 #12

P: n/a
"S.Tobias" <si***@FamOuS.BedBuG.pAlS.INVALID> writes:
In comp.lang.c Keith Thompson <ks***@mib.org> wrote:

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.


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).

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #13

P: n/a
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.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Mar 3 '06 #14

P: n/a
On 2006-03-03, Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <si***@FamOuS.BedBuG.pAlS.INVALID> writes:
In comp.lang.c Keith Thompson <ks***@mib.org> wrote:

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.


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?
Mar 3 '06 #15

P: n/a
Micah Cowan <mi***@cowan.name> writes:
Keith Thompson <ks***@mib.org> writes:
"Robin Haigh" <ec*****@leeds.ac.uk> writes: [...]
> 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.


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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #16

P: n/a
Jordan Abel <ra*******@gmail.com> writes:
On 2006-03-03, Keith Thompson <ks***@mib.org> wrote:
"S.Tobias" <si***@FamOuS.BedBuG.pAlS.INVALID> writes: [...]
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).


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.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 3 '06 #17

P: n/a
Keith Thompson <ks***@mib.org> writes:
Micah Cowan <mi***@cowan.name> writes:
Keith Thompson <ks***@mib.org> writes:
"Robin Haigh" <ec*****@leeds.ac.uk> writes: [...] > 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.


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.
Mar 4 '06 #18

P: n/a
WaterWalk wrote:

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/>
Mar 4 '06 #19

P: n/a
In comp.std.c Keith Thompson <ks***@mib.org> wrote:

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
Mar 4 '06 #20

P: n/a
P Boy wrote:
Here http://www.le.ac.uk/cc/tutorials/c/ccccstrc.html is a good source
about struct copying.


I would not recommend that start. It recommends doing things which are
generally considered bad style around here, such as casting the return
value of malloc (I can only remember one person on this group with a
good reason to do this, and his reason does not apply to most people)
and using sizeof(type) rather than sizeof *ptr to work out how much
space to allocate. I.e. the web page recommends using, and I quote:
ptr = (*int) malloc(sizeof(int)*N)
The generally recommended style around here is the far simpler and more
maintainable form:
ptr = malloc(N * sizeof *ptr);
Fewer characters to type, remains correct of the type of ptr changes,
and does not hide the required diagnostic if there is no declaration of
malloc in scope.

It also goes on to recommend using #define to create an alias for a
type, which is what the typedef keyword is for, and typedef has
advantages over a #define.

Also, please quote some context when replying so that people know what
you are replying to. It is entirely possible that some people might see
your reply but not the original message. See
http://cfaj.freeshell.org/google/ for more about this problem and how to
post correctly through Google. Also see my sig for a link to a lot
more information on what is considered acceptable in the group and why.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Mar 5 '06 #21

P: n/a
Micah Cowan <mi***@cowan.name> writes:
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.


Keith Thompson wrote: 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.


That's a good point.

Can we therefore conclude that structure assignment cannot be done
as member-by-member assignments on systems that allow trap
representations, on the theory that assignment of a member having
a trap value incurs undefined behavior (or at least affects the overall
struct assignment operation)?

-drt

Mar 6 '06 #22

P: n/a
"David R Tribble" <da***@tribble.com> writes:
Micah Cowan <mi***@cowan.name> writes:
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.


Keith Thompson wrote:
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.


That's a good point.

Can we therefore conclude that structure assignment cannot be done
as member-by-member assignments on systems that allow trap
representations, on the theory that assignment of a member having
a trap value incurs undefined behavior (or at least affects the overall
struct assignment operation)?


I think it means that the assignment can be done in any way the
implementation chooses, as long as any defined values of members in
the source are properly copied to the target, and as long as any
member trap representations in the source don't cause anything "bad"
to happen (defining "bad" is left as an exercise).

Accessing a trap representation invokes undefined behavior, but the
implementation is allowed to do so if it knows it won't cause any
problems.

The obvious way to do this is to use the equivalent of memcpy(). In
fact, it seems to me it would have been reasonable to *require* struct
assignment to be done as if by memcpy(). (An implemention might save
some time by not copying uninitialized members, but I doubt that any
real implementation actually does this; the time saved by not copying
padding bytes is unlikely to be significant.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 6 '06 #23

P: n/a
In comp.std.c David R Tribble <da***@tribble.com> wrote:

Can we therefore conclude that structure assignment cannot be done
as member-by-member assignments on systems that allow trap
representations, on the theory that assignment of a member having
a trap value incurs undefined behavior (or at least affects the overall
struct assignment operation)?


No, because your theory doesn't necessarily hold. An implementation is
free to use member-by-member assignment if it knows, or can ensure, that
no untoward behavior will actually occur.

-Larry Jones

Some people just don't have inquisitive minds. -- Calvin
Mar 6 '06 #24

P: n/a
[struct copy]

Keith Thompson wrote:
[...]
The obvious way to do this is to use the equivalent of memcpy(). In
fact, it seems to me it would have been reasonable to *require* struct
assignment to be done as if by memcpy(). (An implemention might save
some time by not copying uninitialized members, but I doubt that any
real implementation actually does this; the time saved by not copying
padding bytes is unlikely to be significant.)


Pathological cases can be devised:

struct Foo
{
unsigned m1: 8;
unsigned :24;

unsigned m2: 8;
unsigned :24;

unsigned m3: 8;
unsigned :24;

unsigned m4: 8;
unsigned :24;
};

You could make the argument that copying only the first 8 bits of each
32-bit chunk of the structure could be faster than copying each entire
32-bit chunk.

-drt

Mar 7 '06 #25

P: n/a

Keith Thompson wrote:
Micah Cowan <mi***@cowan.name> writes:
Keith Thompson <ks***@mib.org> writes:
"Robin Haigh" <ec*****@leeds.ac.uk> writes: [...] > 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.


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.


Thanks for all the replies. Now I think I become more acquainted with
struct assignment.

I notice the term "trap representation" appears. I don't know exactly
what it means. Would you please give me some hints?

Mar 9 '06 #26

P: n/a
"WaterWalk" <to********@163.com> writes:
[...]
I notice the term "trap representation" appears. I don't know exactly
what it means. Would you please give me some hints?


C99 6.2.6.1p5:

Certain object representations need not represent a value of the
object type. If the stored value of an object has such a
representation and is read by an lvalue expression that does not
have character type, the behavior is undefined. If such a
representation is produced by a side effect that modifies all or
any part of the object by an lvalue expression that does not have
character type, the behavior is undefined. Such a representation
is called a _trap representation_.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Mar 9 '06 #27

P: n/a
Keith Thompson wrote:
"WaterWalk" <to********@163.com> writes:
I notice the term "trap representation" appears. I don't know exactly
what it means. Would you please give me some hints?

C99 6.2.6.1p5:
Certain object representations need not represent a value of the
object type. If the stored value of an object has such a
representation and is read by an lvalue expression that does not
have character type, the behavior is undefined. If such a
representation is produced by a side effect that modifies all or
any part of the object by an lvalue expression that does not have
character type, the behavior is undefined. Such a representation
is called a _trap representation_.


And the name is meant to suggest that the undefined behavior
might be as nasty as a hardware trap, although that actually
occurs only on relatively few platforms. The main thing is
that when a program produces a trap rep the C implementation
doesn't have to handle it "properly" (where "proper" describes
any of the behaviors a programmer might have been expecting).
For example, generated code might depend on a convention that
certain bits of the representation are always 0, so violating
that assumption causes incorrect computation.
Mar 9 '06 #28

P: n/a
Douglas A. Gwyn wrote:
Keith Thompson wrote:
"WaterWalk" <to********@163.com> writes:
I notice the term "trap representation" appears. I don't know exactly
what it means. Would you please give me some hints?


C99 6.2.6.1p5:
Certain object representations need not represent a value of the
object type. If the stored value of an object has such a
representation and is read by an lvalue expression that does not
have character type, the behavior is undefined. If such a
representation is produced by a side effect that modifies all or
any part of the object by an lvalue expression that does not have
character type, the behavior is undefined. Such a representation
is called a _trap representation_.

And the name is meant to suggest that the undefined behavior
might be as nasty as a hardware trap, although that actually
occurs only on relatively few platforms. The main thing is
that when a program produces a trap rep the C implementation
doesn't have to handle it "properly" (where "proper" describes
any of the behaviors a programmer might have been expecting).
For example, generated code might depend on a convention that
certain bits of the representation are always 0, so violating
that assumption causes incorrect computation.


Hardware traps aren't all that unusual. Many systems will
trap if given a `long*' with a few stray "low-order" one-bits.
Some IEEE floating-point systems will respond to "signalling"
operands by generating traps, although I'll grant that most C
implementations appear to prefer operating their IEEE units in
a non-trapping mode. VAX processors had/have a different F-P
scheme that traps on certain invalid operands.

--
Eric Sosman
es*****@acm-dot-org.invalid
Mar 10 '06 #29

This discussion thread is closed

Replies have been disabled for this discussion.