Topic: Q:Unexpected array assignment and VC++ 1.5


Author: andys@thone.demon.co.uk (Andy Sawyer)
Date: 1995/04/10
Raw View
In article <D6MCI8.9AM@jt.dk>, oxhoj_njo@jt.dk (Nicholas Oxhoj) writes:
> It seems to me that VC++ 1.5 has some unexpected behavior when it comes to
> array assignment.
>
> Consider the following example program:
> ---
> struct MyStruct {
>      char str[4];
> };
>
> void main()
> {
>      MyStruct s1 = { "123" }, s2;
>
> //   s2.str = s1.str;   // Illegal
>      s2 = s1;           // Legal???
>
>      printf("str = %s", s2.str);
> }
>
> The first assignment (the one commented out) is caught by the compiler
> which complains that the left hand side is not an l-value. This is what I
> would expect.
>
> The second assignment on the other hand, not only compiles but actually
>  runs.
> This is what I don't understand. I had the clear impression that the default > |> assignment operator for a struct was generated by the compiler by doing
> member-wise assignment, and if any member did not have an assignment
>  operator
> then the default assignment operator would not be generated. It seems pretty > |> obvious (considering the first assignment attempt) that no assignment
>  operator
> exists for char arrays - so what is happening here.
>
> I sincerely hope that some C++ guru can help straighten out my
>  misconceptions.
>

 Not a guru (yet:-), but the reason the second statment (the structure
assignment) works, is by the memberwise copy rule. The _members_ of
MyStruct are str[0], str[1], str[2] and str[3]. The memberwise copy does:

 s2.str[0] = s1.str[0];
 s2.str[1] = s1.str[1];
 s2.str[2] = s1.str[2];
 s2.str[3] = s1.str[3];

 (Althoug the compiler may be smart enough to optimize this into a 32bit
register load & store!)

Regards,
 Andy

--
* Andy Sawyer ** e-mail:andys@thone.demon.co.uk ** Compu$erve:100432,1713 **
 The opinions expressed above are my own, but you are granted the right to
 use and freely distribute them. I accept no responsibility for any injury,
 harm or damage arising from their use.                --   The Management.





Author: chris@alofi.etca.fr (Christian Millour)
Date: 1995/04/07
Raw View
In article <D6MCI8.9AM@jt.dk>, oxhoj_njo@jt.dk (Nicholas Oxhoj) writes:
|> It seems to me that VC++ 1.5 has some unexpected behavior when it comes to
|> array assignment.
|>
|> Consider the following example program:
|> ---
|> struct MyStruct {
|>  char str[4];
|> };
|>
|> void main()
|> {
|>  MyStruct s1 = { "123" }, s2;
|>
|> // s2.str = s1.str;   // Illegal
|>  s2 = s1;           // Legal???
|>
|>  printf("str = %s", s2.str);
|> }
|>
|> The first assignment (the one commented out) is caught by the compiler
|> which complains that the left hand side is not an l-value. This is what I
|> would expect.
|>
|> The second assignment on the other hand, not only compiles but actually runs.
|> This is what I don't understand. I had the clear impression that the default
|> assignment operator for a struct was generated by the compiler by doing
|> member-wise assignment, and if any member did not have an assignment operator
|> then the default assignment operator would not be generated. It seems pretty
|> obvious (considering the first assignment attempt) that no assignment operator
|> exists for char arrays - so what is happening here.
|>
|> I sincerely hope that some C++ guru can help straighten out my misconceptions.
|>

Good question. I'm not a guru but will give it a try...

The primary rationale for using memberwise assignment over bitwise
copy is to ensure that user-defined assignements ops for members
will be called.

What probably happens next is that non-class members are assigned
by default using bitwise copy, especially arrays of built-in types.
This is useful when C++ is used as a `better C' since the alternative
of not generating a default assignment operator would break too much
valid C code. Wrapping fixed sized arrays within structs is indeed
a common C idiom (e.g. for passing by value in function calls).

I don't know how arrays of class objects should be handled. Take the
following code:

#include <iostream.h>
struct I {
  I() : i(0) {}
  I& operator=(const I& o);
  int i;
};

I& I::operator=(const I& o) {i = o.i; cerr << "I::operator=()"<< endl; return *this;}

class S {
public:
  I s[4];
};

int
main() {
  S s1, s2;
  s1 = s2;
}


One the one hand 2nd 2.3.6 explicitely states that assignment is not
defined for arrays. One the other hand Cfront 3.0.2 issues an error
message akin more to implementation limitations than to explicit
language rules:

"sss.cc", line 18: sorry, not implemented: copy of  I[], no memberwise copy for I

Finally, g++ -V2.6.3 -Wall accepts it silently, and invoques
I::operator=() for each element of the array.

I kindof think compilers should issue a warning.

|> Please respond via. e-mail to oxhoj_njo@jt.dk since our news system for some
|> reason has a constant lag of 10-14 days.

did that too.

Cross-posted to comp.std.c++ since I wonder whether the forthcoming
standard has anything to say about it (I hope they don't get fed up
with my doing so...).

Regards,

--chris@etca.fr