Copying struct with array

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David Rasmussen

    Copying struct with array

    If I have this

    struct S
    {
    int arr[5];
    };

    and I do this:

    S s1,s2;

    ....

    s1 = s2;

    what happens?

    Normally, array assignments aren't possible/allowed. If I do s1.arr =
    s2.arr I get a compiler error. If I do s1 = s2 it compiles fine. And it
    even seems like the array is getting copied, not just the pointer to the
    start of the array, at least with g++.

    Is there any difference in semantics here betweeen C and C++?

    /David
  • Siemel Naran

    #2
    Re: Copying struct with array

    "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
    news:40a0fafd$0 $174
    [color=blue]
    > struct S
    > {
    > int arr[5];
    > };[/color]
    [color=blue]
    > s1 = s2;
    >
    > what happens?
    >
    > Normally, array assignments aren't possible/allowed. If I do s1.arr =
    > s2.arr I get a compiler error. If I do s1 = s2 it compiles fine. And it
    > even seems like the array is getting copied, not just the pointer to the
    > start of the array, at least with g++.
    >
    > Is there any difference in semantics here betweeen C and C++?[/color]

    Yes, the assignment copies the array contents, in both C and C++. Same
    thing for the copy constructor.


    Comment

    • Andrey Tarasevich

      #3
      Re: Copying struct with array

      David Rasmussen wrote:[color=blue]
      > If I have this
      >
      > struct S
      > {
      > int arr[5];
      > };
      >
      > and I do this:
      >
      > S s1,s2;
      >
      > ...
      >
      > s1 = s2;
      >
      > what happens?[/color]

      The entire object gets copied. The array is a subobject of that object,
      which means that it gets copied too.
      [color=blue]
      > Normally, array assignments aren't possible/allowed. If I do s1.arr =
      > s2.arr I get a compiler error.[/color]

      Array assignment is possible. Arrays are aggregates, just like structs
      are. Technically, they can be copied the same way structs are. But it is
      not allowed at language level for purely historical reasons.
      [color=blue]
      > If I do s1 = s2 it compiles fine. And it
      > even seems like the array is getting copied, not just the pointer to the
      > start of the array, at least with g++.[/color]

      What pointer? There's no "pointer to the start of the array" in this
      example.
      [color=blue]
      > Is there any difference in semantics here betweeen C and C++?[/color]

      No.

      --
      Best regards,
      Andrey Tarasevich

      Comment

      • David Rasmussen

        #4
        Re: Copying struct with array

        Andrey Tarasevich wrote:[color=blue]
        >[color=green]
        >>Normally, array assignments aren't possible/allowed. If I do s1.arr =
        >>s2.arr I get a compiler error.[/color]
        >
        > Array assignment is possible. Arrays are aggregates, just like structs
        > are. Technically, they can be copied the same way structs are. But it is
        > not allowed at language level for purely historical reasons.
        >[/color]

        Wow. You learn something new everyday... I'm not actually a novice C++
        programmer (well, maybe I am after all).

        So, just to be clear:

        s1.arr = s2.arr isn't possible

        but s1 = s2 is?

        That's weird!

        /David

        Comment

        • David Rasmussen

          #5
          Re: Copying struct with array

          Siemel Naran wrote:[color=blue]
          >
          > Yes, the assignment copies the array contents, in both C and C++. Same
          > thing for the copy constructor.
          >[/color]

          It's really weird that the compiler will copy the array implicitly, but
          not explicitly. As in s1.arr = s2.arr;

          /David

          Comment

          • Karl Heinz Buchegger

            #6
            Re: Copying struct with array

            David Rasmussen wrote:[color=blue]
            >
            > Siemel Naran wrote:[color=green]
            > >
            > > Yes, the assignment copies the array contents, in both C and C++. Same
            > > thing for the copy constructor.
            > >[/color]
            >
            > It's really weird that the compiler will copy the array implicitly, but
            > not explicitly. As in s1.arr = s2.arr;[/color]

            If I remember correctly, the same was true with structures in ancient
            times (K&R C). It's just that the rules have been changed for structs
            but not for arrays. I guess to much code would have been broken at
            the time of change.

            --
            Karl Heinz Buchegger
            kbuchegg@gascad .at

            Comment

            • John Harrison

              #7
              Re: Copying struct with array


              "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
              news:40a10a3c$0 $184$edfadb0f@d text02.news.tel e.dk...[color=blue]
              > Siemel Naran wrote:[color=green]
              > >
              > > Yes, the assignment copies the array contents, in both C and C++. Same
              > > thing for the copy constructor.
              > >[/color]
              >
              > It's really weird that the compiler will copy the array implicitly, but
              > not explicitly. As in s1.arr = s2.arr;
              >[/color]

              Not really, it copies each member of the array like this

              for (int i = 0; i< 5; ++i)
              s1.arr[i] = s2.arr[i];

              Nothing wierd about it, that's the definition of a default copy
              ctor/assignment op, they do a memberwise copy.

              john


              Comment

              • David Rasmussen

                #8
                Re: Copying struct with array

                John Harrison wrote:[color=blue]
                >
                > Not really, it copies each member of the array like this
                >
                > for (int i = 0; i< 5; ++i)
                > s1.arr[i] = s2.arr[i];
                >
                > Nothing wierd about it, that's the definition of a default copy
                > ctor/assignment op, they do a memberwise copy.
                >[/color]

                Sure, but then s1.arr = s2.arr should do the same.

                s1 = s2 does a memberwise copy of the structs. That is, each member is
                copied. But in the case of the array, this copying is a "magical"
                operator that we can't access any other way.
                What happens if we copy a struct that has a member that has a private
                copy constructor and a private assignment operator?
                Like:

                class M
                {
                // private copy constructor and assignment operator
                };

                struct S
                {
                M m;
                };

                S s1,s2;

                s1 = s2;

                In this case, s1.m = s2.m isn't possible. So I wouldn't expect s1 = s2
                to be.

                /David

                Comment

                • John Harrison

                  #9
                  Re: Copying struct with array


                  "David Rasmussen" <david.rasmusse n@gmx.net> wrote in message
                  news:40a115e6$0 $173$edfadb0f@d text02.news.tel e.dk...[color=blue]
                  > John Harrison wrote:[color=green]
                  > >
                  > > Not really, it copies each member of the array like this
                  > >
                  > > for (int i = 0; i< 5; ++i)
                  > > s1.arr[i] = s2.arr[i];
                  > >
                  > > Nothing wierd about it, that's the definition of a default copy
                  > > ctor/assignment op, they do a memberwise copy.
                  > >[/color]
                  >
                  > Sure, but then s1.arr = s2.arr should do the same.
                  >[/color]

                  It can't, its just history

                  void f(int a[6])
                  {
                  }

                  int main()
                  {
                  int b[6];
                  f(b);
                  }

                  What you are saying is that given this code array b should be copied
                  wholesale to the array parameter a. That would be logical, but unfortunately
                  since the dawn of time C (and hence C++) has defined different behaviour for
                  that code (a is really a pointer, array decays to pointer to the first
                  element etc etc). Too late to change now.

                  I think the original decision to treat arrays in this special way was made
                  because of concerns about the efficiency of copying large arrays.

                  But structs are different because in the original C

                  void f(struct S a)
                  {
                  }

                  int main()
                  {
                  struct S b;
                  f(b);
                  }

                  was just plain illegal. So when it was decided that actually being able to
                  copy structs was a useful thing, there wasn't a legacy of C code that
                  defined different behaviour.

                  john


                  Comment

                  • JKop

                    #10
                    Re: Copying struct with array

                    David Rasmussen posted:
                    [color=blue]
                    > Normally, array assignments aren't possible/allowed. If I do s1.arr =
                    > s2.arr I get a compiler error.[/color]


                    That's exactly like writing:


                    5 = 6;

                    "Hello" = "Goodbye";


                    As I'm about to explain:


                    unsigned int Ages[7];



                    Now, if I write:


                    unsigned int k = Ages[0];


                    Then the value stored in the variable entitled "Ages[0]" gets copied to the
                    variable entitled "k". No problemo. Now... look at the following:

                    k = Ages;

                    "Ages" written on it's own, without an array index, is exactly like writing
                    "&Ages[0]", ie. it's equal to the address of the first variable in the
                    array. Now, take your example:

                    s1.ar = s2.ar;


                    That is equal to:

                    &s1.ar[0] = &s2.ar[0];


                    That's exactly like writing:

                    unsigned int k = 4;
                    &k = 27873;

                    You're not changing the value of a variable at all! You're trying to change
                    the address of a variable! Self-explanatory I hope!

                    [color=blue]
                    > If I do s1 = s2 it compiles fine.[/color]


                    unsigned int a = 5;
                    unsigned int b = 6;

                    a = b;

                    b = a;

                    &a = &b; //ERROR


                    All you are doing is copying memory! As so:

                    S s1;
                    S s2;

                    s1 = s2;

                    s2 = s1;

                    &s1 = &s2; //ERROR




                    Now, let's try solve your problemo:

                    unsigned int Cats[48];
                    unsigned int Dogs[48];

                    To copy the whole lot, you'd have to do:

                    Cat[0] = Dog[0];
                    Cat[1] = Dog[1];
                    Cat[2] = Dog[2];
                    Cat[3] = Dog[3];

                    Why do we have to do this? Because there's no variable called "Cat", nor is
                    there a varible called "Dog". There's a variable called "Cat[0]" alright, as
                    is there a variable called "Dog[0]". So why is the following valid?:

                    unsigned int* pCats = Cats;

                    There's no reason! It makes no sense at all! Someone just decided it was
                    more convenient than:

                    unsigned int* pCats = &Cats[0];


                    I'll get to the point, how should we do it? Well, what you've done is
                    actually very clever and it's the best thing I've ever seen for doing it!
                    Take the following:

                    void RegisterName(co nst char* const pNameToRegister )
                    {
                    //Here, we need to keep a record of the name, so we copy it.
                    //Normally, I would use strcpy, as follows:

                    char NameBuffer[30];
                    strcpy(NameBuff er, pNameToRegister );

                    //But you've come up with a brilliant idea!!

                    struct StringCopierStr uctureBuffer
                    {
                    char NameBuffer[30];
                    };

                    StringCopierStr uctureBuffer* pInput = (StringCopierSt ructureBuffer*)
                    pNameToRegister ;

                    StringCopierStr uctureBuffer pStored;

                    pStored = *pInput;

                    //We don't need strcpy! We can use this with any sort of array!

                    //I wrote the above code in about 5 mins and there's likely to be a
                    //thousand errors in it, but you get the picture.

                    }



                    -JKop

                    Comment

                    • Andrey Tarasevich

                      #11
                      Re: Copying struct with array

                      JKop wrote:[color=blue]
                      > Now, take your example:
                      >
                      > s1.ar = s2.ar;
                      >
                      > That is equal to:
                      >
                      > &s1.ar[0] = &s2.ar[0];
                      >
                      > That's exactly like writing:
                      >
                      > unsigned int k = 4;
                      > &k = 27873;
                      >
                      > You're not changing the value of a variable at all! You're trying to change
                      > the address of a variable! Self-explanatory I hope!
                      > ...[/color]

                      This doesn't really explain much. Yes, the standard array-to-pointer
                      conversion is the immediate formal reason why such code won't compile,
                      but the _real_ question is why array assignment (and array copying)
                      contexts were not excluded from the list of contexts where
                      array-to-pointer conversion is applied. Today there is no formal reason
                      for it to be this way, although there probably was one a rather long
                      time ago.

                      There is no technical problems with requiring the language to perform
                      array assignment in

                      s1.ar = s2.ar;

                      But doing this will break the compatibility with previous version of
                      language specification.

                      Note also that one specific array-related context does actually copy arrays:

                      char lpsz[] = "Hello world";

                      --
                      Best regards,
                      Andrey Tarasevich

                      Comment

                      Working...