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

Struct assignment

P: n/a
If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b. Question is:

1). is b.s now ptr to a.s ? (I think so)
If so, what happens if for instance variable 'a' goes out of scope (?)

2). Does the compiler generate an implicit "memcpy" or "memmove" behind
the scenes when it sees an assignment like this (to avoid dangling ptrs)?
Jun 30 '07 #1
Share this Question
Share on Google+
24 Replies


P: n/a

"Grey Alien" <gr**@andromeda.comwrote in message
news:er*********************@bt.com...
If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b. Question is:

1). is b.s now ptr to a.s ? (I think so)
If so, what happens if for instance variable 'a' goes out of scope (?)

2). Does the compiler generate an implicit "memcpy" or "memmove" behind
the scenes when it sees an assignment like this (to avoid dangling ptrs)?
The answer is 2. A structure assignment will cause a call to memcpy to be
made, or equivalent code emitted if the structure is small enough to make
this wasteful and the compiler is clever.
However if structures contain pointers then the values of the pointers are
overwritten. So you have to be extremely careful not to orphan memory or
create peculiar bugs with aliases.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 30 '07 #2

P: n/a
On Jun 30, 9:43 am, Grey Alien <g...@andromeda.comwrote:
If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];

} a, b;

And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b.
Question is:

1). is b.s now ptr to a.s ? (I think so)
I think you are confusing arrays and pointers. Since a.s is an array,
a.s[0] to a.s[LONG_ENOUGH-1] are actually stored in the structure and
are copied by the assignment.

If a.s were just a pointer to memory allocated elsewhere the
assignment would just copy the pointer.
2). Does the compiler generate an implicit "memcpy"
or "memmove" behind the scenes when it sees an
assignment like this (to avoid dangling ptrs)?
There is an explicit copy since a.s is an array. If a.s
were a pointer there would not be an implicit copy, and
Bad Things such as dangling pointers could result.

-thomas

Jun 30 '07 #3

P: n/a
Grey Alien wrote, On 30/06/07 17:43:
If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b.
It is not a bitwise copy, it is a copy of all the elements in the struct.
Question is:

1). is b.s now ptr to a.s ? (I think so)
Since b.s was not defined as a pointer, what makes you think an
assignment could magically transform it from being an array in to being
a pointer? You need to read section 6 of the comp.lang.c FAQ at
http://c-faq.com/ specifically the questions dealing with whether
pointers and arrays are the same thing.
If so, what happens if for instance variable 'a' goes out of scope (?)

2). Does the compiler generate an implicit "memcpy" or "memmove" behind
the scenes when it sees an assignment like this (to avoid dangling ptrs)?
It is very rare for C to do things behind your back. Had there been
pointers in your struct (which there were not) then after the assignment
they would point to the same place as they point in the original struct,
and when that place is no longer valid (an automatic that goes out of
scope, for example) the pointers are no longer valid.
--
Flash Gordon
Jun 30 '07 #4

P: n/a

"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
news:hh************@news.flash-gordon.me.uk...
Grey Alien wrote, On 30/06/07 17:43:
>If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b.

It is not a bitwise copy, it is a copy of all the elements in the struct.
Question is:

1). is b.s now ptr to a.s ? (I think so)

Since b.s was not defined as a pointer, what makes you think an assignment
could magically transform it from being an array in to being a pointer?
You need to read section 6 of the comp.lang.c FAQ at http://c-faq.com/
specifically the questions dealing with whether pointers and arrays are
the same thing.
Its easy to see where the confusion comes from. There are situations where
pointers degenerate into pointers , the OP probably had that in mind

Jun 30 '07 #5

P: n/a
Serve Lau said:

<snip>
Its easy to see where the confusion comes from. There are situations
where pointers degenerate into pointers ,
Pointers always degenerate into pointers.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 30 '07 #6

P: n/a
Serve Lau wrote, On 30/06/07 19:53:
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
news:hh************@news.flash-gordon.me.uk...
>Grey Alien wrote, On 30/06/07 17:43:
<snip>
>>1). is b.s now ptr to a.s ? (I think so)
Since b.s was not defined as a pointer, what makes you think an assignment
could magically transform it from being an array in to being a pointer?
You need to read section 6 of the comp.lang.c FAQ at http://c-faq.com/
specifically the questions dealing with whether pointers and arrays are
the same thing.

Its easy to see where the confusion comes from. There are situations where
pointers degenerate into pointers , the OP probably had that in mind
In my opinion it is only easy to confuse arrays and pointers if it is
badly taught. If arrays and pointers are taught as fundamentally
different concepts and *then* the way array names degenerate to pointers
to the first element is explained there will not be anything like the
problems. In one-to-one sessions I've been able to explain the basics of
arrays pointers to non-computer people in minutes (I needed to so I
could explain approximately what was the cause of a problem), although I
did not go on to how things are done in C.
--
Flash Gordon
Jun 30 '07 #7

P: n/a
Flash Gordon <sp**@flash-gordon.me.ukwrites:
Grey Alien wrote, On 30/06/07 17:43:
>If I have the ff struct:
struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:
a.i = 42 ;
strcpy(a.s,"test");
b.i = 100 ;
b = a ;
at this point, a (bitwise?) copy of a is made to b.

It is not a bitwise copy, it is a copy of all the elements in the struct.
Yes -- and that can be, and commonly is, implemented as a bitwise copy
of the struct.

Suppose there's a gap between the members "i" and "s". After the
assignment "b = a;", the gaps in "a" and "b" may or may not have the
same contents. The assignment can be done either as a bitwise copy or
by copying the members one-by-one, leaving any gaps alone.

99% of the type, this doesn't matter because you're never going to
look at what's in the gaps anyway.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 30 '07 #8

P: n/a
Richard Heathfield wrote, On 30/06/07 20:56:
Serve Lau said:

<snip>
>Its easy to see where the confusion comes from. There are situations
where pointers degenerate into pointers ,

Pointers always degenerate into pointers.
No they don't, they stay as pointers ;-)

Knowing what Serve Lau must have intended I read it as "where arrays
degenerate...".
--
Flash Gordon
Jun 30 '07 #9

P: n/a
Flash Gordon said:
Richard Heathfield wrote, On 30/06/07 20:56:
>Serve Lau said:

<snip>
>>Its easy to see where the confusion comes from. There are situations
where pointers degenerate into pointers ,

Pointers always degenerate into pointers.

No they don't, they stay as pointers ;-)

Knowing what Serve Lau must have intended I read it as "where arrays
degenerate...".
I know. Actually, arrays never actually do that. We often say they do,
but we're just being lazy. What we really mean is that the name of an
array, when used in an expression, is often (indeed, *usually*) treated
as if it were a pointer to the array's first element. The array itself
never "degenerates" (or "decays", as it is usually put) at all.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 30 '07 #10

P: n/a
Keith Thompson wrote, On 30/06/07 21:30:
Flash Gordon <sp**@flash-gordon.me.ukwrites:
>Grey Alien wrote, On 30/06/07 17:43:
>>If I have the ff struct:
struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:
a.i = 42 ;
strcpy(a.s,"test");
b.i = 100 ;
b = a ;
at this point, a (bitwise?) copy of a is made to b.
It is not a bitwise copy, it is a copy of all the elements in the struct.

Yes -- and that can be, and commonly is, implemented as a bitwise copy
of the struct.

Suppose there's a gap between the members "i" and "s". After the
assignment "b = a;", the gaps in "a" and "b" may or may not have the
same contents. The assignment can be done either as a bitwise copy or
by copying the members one-by-one, leaving any gaps alone.

99% of the type, this doesn't matter because you're never going to
look at what's in the gaps anyway.
Where there are multiple representations for the same value the
representation could change. It is important for the OP to know this
IMHO so that s/he does not assume that memcmp can be used safely.
--
Flash Gordon
Jun 30 '07 #11

P: n/a

"Grey Alien" <gr**@andromeda.comha scritto nel messaggio news:er*********************@bt.com...
If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b. Question is:

1). is b.s now ptr to a.s ? (I think so)
No, since it is an array, not a pointer.
If so, what happens if for instance variable 'a' goes out of scope (?)

2). Does the compiler generate an implicit "memcpy" or "memmove" behind the scenes when it sees an assignment like this?
It could, but it needn't. For example, padding bits needn't be
copied.
Jul 1 '07 #12

P: n/a
Malcolm McLean wrote On 06/30/07 13:05,:
"Grey Alien" <gr**@andromeda.comwrote in message
news:er*********************@bt.com...
>>If I have the ff struct:

struct A
{
unsigned int i;
char s[LONG_ENOUGH];
} a, b;
And use them in code like this:

a.i = 42 ;
strcpy(a.s,"test");

b.i = 100 ;

b = a ;

at this point, a (bitwise?) copy of a is made to b. Question is:

1). is b.s now ptr to a.s ? (I think so)
If so, what happens if for instance variable 'a' goes out of scope (?)

2). Does the compiler generate an implicit "memcpy" or "memmove" behind
the scenes when it sees an assignment like this (to avoid dangling ptrs)?

The answer is 2. A structure assignment will cause a call to memcpy to be
made, or equivalent code emitted if the structure is small enough to make
this wasteful and the compiler is clever. [...]
The compiler *may* do this, but it is not required
to copy padding bytes and padding bits. Assignment only
copies the value; padding bytes and bits are not part of
the value of a struct, and might not be copied -- as they
would be if memcpy() or an equivalent were used.

--
Er*********@sun.com
Jul 2 '07 #13

P: n/a
On Jul 3, 2:59 am, Eric Sosman <Eric.Sos...@sun.comwrote:
The compiler *may* do this, but it is not required
to copy padding bytes and padding bits. Assignment only
copies the value; padding bytes and bits are not part of
the value of a struct, and might not be copied -- as they
would be if memcpy() or an equivalent were used.
Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.

So does the assignment 't = s' cause undefined
behaviour by copying the values of uninitialized
array members?

Jul 3 '07 #14

P: n/a
On Jul 2, 8:02 pm, Old Wolf <oldw...@inspire.net.nzwrote:
On Jul 3, 2:59 am, Eric Sosman <Eric.Sos...@sun.comwrote:
The compiler *may* do this, but it is not required
to copy padding bytes and padding bits. Assignment only
copies the value; padding bytes and bits are not part of
the value of a struct, and might not be copied -- as they
would be if memcpy() or an equivalent were used.

Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.
Actually you are wrong about that, 9899:1999 6.7.8p21:

"If there are fewer initializers in a brace-enclosed list than there
are elements or members
of an aggregate, or fewer characters in a string literal used to
initialize an array of known
size than there are elements in the array, the remainder of the
aggregate shall be
initialized implicitly the same as objects that have static storage
duration."

Robert Gamble

Jul 3 '07 #15

P: n/a
Old Wolf <ol*****@inspire.net.nzwrites:
On Jul 3, 2:59 am, Eric Sosman <Eric.Sos...@sun.comwrote:
> The compiler *may* do this, but it is not required
to copy padding bytes and padding bits. Assignment only
copies the value; padding bytes and bits are not part of
the value of a struct, and might not be copied -- as they
would be if memcpy() or an equivalent were used.

Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.

So does the assignment 't = s' cause undefined
behaviour by copying the values of uninitialized
array members?
Not in n1124. n1124 6.2.6.1p6 says:

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.

but that wording is not in the original C99 standard, or in C90; C99
instead says:

The values of padding bytes shall not affect whether the value of
such an object is a trap representation. Those bits of a structure
or union object that are in the same byte as a bit-field member,
but are not part of that member, shall similarly not affect
whether the value of such an object is a trap representation.

I suspect that the intent all along was that your example would not
invoke undefined behavior, but it had never been stated properly,
which is why it needed to be corrected in n1124.

By a strict reading of the original C99 or C90 standard, I think it
could be argued that your example does invoke undefined behavior. I'd
be interested in seeing an argument that it doesn't.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #16

P: n/a
Robert Gamble <rg*******@gmail.comwrites:
On Jul 2, 8:02 pm, Old Wolf <oldw...@inspire.net.nzwrote:
[...]
>Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.

Actually you are wrong about that, 9899:1999 6.7.8p21:

"If there are fewer initializers in a brace-enclosed list than there
are elements or members of an aggregate, or fewer characters in a
string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration."
Argh, you're right. My comment about n1124 6.2.6.1p6 do not apply to
the above example.

They do, however, apply to the following:

struct S
{
char s[10];
};

struct S s;
struct S t;
strcpy(s.s, "hello");
t = s;

(Assume that this appears inside a function definition, and that a
"#include <string.h>" is visible.)

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #17

P: n/a
Richard Heathfield <r...@see.sig.invalidwrote:
Flash Gordon said:
Richard Heathfield wrote, On 30/06/07 20:56:
Serve Lau said:
Its easy to see where the confusion comes from. There
are situations where pointers degenerate into pointers,
>
Pointers always degenerate into pointers.
No they don't, they stay as pointers ;-)

Knowing what Serve Lau must have intended I read it as
"where arrays degenerate...".

I know. Actually, arrays never actually do that. We often
say they do, but we're just being lazy. What we really
mean is that the name of an array, when used in an
expression, is often (indeed, *usually*) treated as if it
were a pointer to the array's first element.
The effect is not limited to named arrays...

int (*ap)[20] = malloc(sizeof *ap);
int *ip = *ap;
The array itself never "degenerates" (or "decays", as it
is usually put) at all.
There is change from an aggregate type to a non-aggregate type.
We could say 'converted' as the standard does, but decay is
more descriptive and notwithstanding. I don't see that as being
'lazy'.

--
Peter

Jul 3 '07 #18

P: n/a
Old Wolf said:

<snip>
>
Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.
Not so. A part-initialisation is sufficient to invoke the static default
initialiser rule.
So does the assignment 't = s' cause undefined
behaviour by copying the values of uninitialized
array members?
No, because there aren't any.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jul 3 '07 #19

P: n/a
On Mon, 02 Jul 2007 19:38:12 -0700, Peter Nilsson <ai***@acay.com.au>
wrote:
>Richard Heathfield <r...@see.sig.invalidwrote:
>Flash Gordon said:
Richard Heathfield wrote, On 30/06/07 20:56:
Serve Lau said:
Its easy to see where the confusion comes from. There
are situations where pointers degenerate into pointers,

Pointers always degenerate into pointers.

No they don't, they stay as pointers ;-)

Knowing what Serve Lau must have intended I read it as
"where arrays degenerate...".

I know. Actually, arrays never actually do that. We often
say they do, but we're just being lazy. What we really
mean is that the name of an array, when used in an
expression, is often (indeed, *usually*) treated as if it
were a pointer to the array's first element.

The effect is not limited to named arrays...

int (*ap)[20] = malloc(sizeof *ap);
int *ip = *ap;
>The array itself never "degenerates" (or "decays", as it
is usually put) at all.

There is change from an aggregate type to a non-aggregate type.
We could say 'converted' as the standard does, but decay is
more descriptive and notwithstanding. I don't see that as being
'lazy'.
Why generate new words to describe what the standard explains very
clearly. With three exception, an expression of array type
**evaluates** to the address of the first element with type pointer to
element type. No decay, no degeneration, no change from aggregate to
non-aggregate, no conversion. Just an evaluation.
Remove del for email
Jul 3 '07 #20

P: n/a
Barry Schwarz <sc******@doezl.netwrites:
On Mon, 02 Jul 2007 19:38:12 -0700, Peter Nilsson <ai***@acay.com.au>
wrote:
[...]
>>There is change from an aggregate type to a non-aggregate type.
We could say 'converted' as the standard does, but decay is
more descriptive and notwithstanding. I don't see that as being
'lazy'.

Why generate new words to describe what the standard explains very
clearly. With three exception, an expression of array type
**evaluates** to the address of the first element with type pointer to
element type. No decay, no degeneration, no change from aggregate to
non-aggregate, no conversion. Just an evaluation.
The standard differs with you. C99 6.3.2.1p3:

Except when it is the operand of the sizeof operator or the unary
& operator, or is a string literal used to initialize an array, an
expression that has type "array of _type_" is converted to an
expression with type "pointer to _type_" that points to the
initial element of the array object and is not an lvalue. If the
array object has register storage class, the behavior is
undefined.

Note the use of the word "converted".

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #21

P: n/a

"Keith Thompson" <ks***@mib.orgha scritto nel messaggio news:ln************@nuthaus.mib.org...
Robert Gamble <rg*******@gmail.comwrites:
>On Jul 2, 8:02 pm, Old Wolf <oldw...@inspire.net.nzwrote:
[...]
>>Something that just occurred to me. Say we
have:
struct S
{
char s[10];
};

struct S s = { "hello" };
struct S t;
t = s;

Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.

Actually you are wrong about that, 9899:1999 6.7.8p21:

"If there are fewer initializers in a brace-enclosed list than there
are elements or members of an aggregate, or fewer characters in a
string literal used to initialize an array of known size than there
are elements in the array, the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage
duration."

Argh, you're right. My comment about n1124 6.2.6.1p6 do not apply to
the above example.

They do, however, apply to the following:

struct S
{
char s[10];
};

struct S s;
struct S t;
strcpy(s.s, "hello");
t = s;

(Assume that this appears inside a function definition, and that a
"#include <string.h>" is visible.)
I think on a system where char is signed, and the equivalent of the
most negative integer (for two's complement) or negative zero (for
ones' complement or sign and magnitude) is a trap, and s[8]
happened to be such a representation...
Jul 3 '07 #22

P: n/a
"Army1987" <pl********@for.itwrites:
"Keith Thompson" <ks***@mib.orgha scritto nel messaggio
news:ln************@nuthaus.mib.org...
[...]
>Argh, you're right. My comment about n1124 6.2.6.1p6 do not apply to
the above example.

They do, however, apply to the following:

struct S
{
char s[10];
};

struct S s;
struct S t;
strcpy(s.s, "hello");
t = s;

(Assume that this appears inside a function definition, and that a
"#include <string.h>" is visible.)

I think on a system where char is signed, and the equivalent of the
most negative integer (for two's complement) or negative zero (for
ones' complement or sign and magnitude) is a trap, and s[8]
happened to be such a representation...
Ok, let's consider a perhaps more realistic example (characters
introduce other issues).

#define MAX_VECTOR_LEN 100

struct int_vector {
int len;
int vec[MAX_VECTOR_LEN];
};

int main(void)
{
struct int_vector v1, v2;

v1.len = 3;
v1.vec[0] = 10;
v1.vec[1] = 20;
v1.vec[2] = 30;

v2 = v1;
return 0;
}

v1.vec contains 3 initialized int element, and 97 uninitialized int
elements. The assignment "v2 = v1;" copies all 100 elements.

The new wording in n1124 makes it clear that structures don't have
trap representations, so the assignment is well defined, even though
the final values of the uninitialized elements are not. (I don't
think it's even clear that v1.vec[50] == v2.vec[50].)

In the original C99, though, since the code is accessing uninitialized
objects, it could invoke undefined behavior. Even in C90, which
didn't have the explicit concept of trap representations, accessing an
uninitialized int still invokes UB. Or consider the same code with
arrays of a floating-point or pointer type.

Now I'd be surprised if any real-world C90 or C99 implementation
actually had a problem with this. I doubt that any real compiler
would implement struct assignment using lower-level operations that
can trap on bad data; it's much easier to do the equivalent of calling
memcpy without worrying about the contents. I'm sure that's why the
committee felt free to make this change in TC2, which was incorporated
into N1124.

But the DS9K compiler probably does something really nasty with this
code unless you specifically invoke it in N1124-compliant mode.

--
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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jul 3 '07 #23

P: n/a
On Jul 3, 5:30 pm, Richard Heathfield <r...@see.sig.invalidwrote:
Old Wolf said:
Initializing an automatic array from a string
literal is only guaranteed to initialize the
characters of the string and the null terminator
- it could leave subsequent array entries (in
this case, indices 6 through 9) uninitialized.

Not so. A part-initialisation is sufficient to invoke the static default
initialiser rule.
Ok. I must be thinking of that other language with
similar syntax. I asserted as much as you said once
in a newsgroup post (although I forget which one),
and was quickly rebuffed with standard quotes.

Jul 3 '07 #24

P: n/a
On Jul 3, 2:39 pm, Keith Thompson <k...@mib.orgwrote:
"Army1987" <please....@for.itwrites:
"Keith Thompson" <k...@mib.orgha scritto nel messaggio
news:ln************@nuthaus.mib.org...
[...]
Argh, you're right. My comment about n1124 6.2.6.1p6 do not apply to
the above example.
They do, however, apply to the following:
struct S
{
char s[10];
};
struct S s;
struct S t;
strcpy(s.s, "hello");
t = s;
(Assume that this appears inside a function definition, and that a
"#include <string.h>" is visible.)
I think on a system where char is signed, and the equivalent of the
most negative integer (for two's complement) or negative zero (for
ones' complement or sign and magnitude) is a trap, and s[8]
happened to be such a representation...

Ok, let's consider a perhaps more realistic example (characters
introduce other issues).

#define MAX_VECTOR_LEN 100

struct int_vector {
int len;
int vec[MAX_VECTOR_LEN];

};

int main(void)
{
struct int_vector v1, v2;

v1.len = 3;
v1.vec[0] = 10;
v1.vec[1] = 20;
v1.vec[2] = 30;

v2 = v1;
return 0;

}

v1.vec contains 3 initialized int element, and 97 uninitialized int
elements. The assignment "v2 = v1;" copies all 100 elements.

The new wording in n1124 makes it clear that structures don't have
trap representations, so the assignment is well defined, even though
the final values of the uninitialized elements are not.
>(I don't think it's even clear that v1.vec[50] == v2.vec[50].)
I think any conforming implementation could very well NOT copy
uninitialized values during struct assignment. So your paranthetical
remark is very much valid.

As per the standards value stored in an uninitialized variable is
"indeterminate". Moreover accessing an uninitialized value invokes UB.
So the expression v1.vec[50]==v2.vec[50] invokes UB. So one possible
behavior is that this equality might fail. Therefore I believe that a
conforming implementation could very well leave the uninitialized
values, uncopied because accessing it produces UB.

Even if the uninitialized values ARE copied, I would expect that this
equality test might fail because the standards uses the word
"indeterminate" which means that value of uninitialized variable might
be changing "dynamically".
/*All declarations and code snippets as in Thompson's code*/
#define MAX_VECTOR_LEN 100

struct int_vector {
int len;
int vec[MAX_VECTOR_LEN];

};

int main(void)
{
struct int_vector v1, v2;

v1.len = 3;
v1.vec[0] = 10;
v1.vec[1] = 20;
v1.vec[2] = 30;

v2 = v1;/*Assume uninitialized values are also copied*/

if(v1.vec[50]==v2.vec[50])
{
printf("Equal from 1st test\n");

}
if(v1.vec[50]==v2.vec[50])
{
printf("Equal from 2nd test of equality\n");

}
return 0;
}
There is a very good probability that the output produced is only:
Equal from 1st test
After executing the first equality test, v1.vec[50] might take some
other value not equal to v2.vec[50], because its value is
"indeterminate". This will cause the second equality test to fail.
>
In the original C99, though, since the code is accessing uninitialized
objects, it could invoke undefined behavior. Even in C90, which
didn't have the explicit concept of trap representations, accessing an
uninitialized int still invokes UB. Or consider the same code with
arrays of a floating-point or pointer type.

Now I'd be surprised if any real-world C90 or C99 implementation
actually had a problem with this. I doubt that any real compiler
would implement struct assignment using lower-level operations that
can trap on bad data; it's much easier to do the equivalent of calling
memcpy without worrying about the contents. I'm sure that's why the
committee felt free to make this change in TC2, which was incorporated
into N1124.

But the DS9K compiler probably does something really nasty with this
code unless you specifically invoke it in N1124-compliant mode.
Jul 3 '07 #25

This discussion thread is closed

Replies have been disabled for this discussion.