Struct assignment

K

Keith Thompson

Barry Schwarz said:
[...]
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".
 
A

Army1987

Keith Thompson said:
Robert Gamble said:
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...
 
K

Keith Thompson

Army1987 said:
"Keith Thompson" <[email protected]> ha scritto nel messaggio
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.
 
O

Old Wolf

Old Wolf said:

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

CryptiqueGuy

Army1987 said:
"Keith Thompson" <[email protected]> ha scritto nel messaggio
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.
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top