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

Copying struct with array

P: n/a
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
Jul 22 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a
"David Rasmussen" <da*************@gmx.net> wrote in message
news:40a0fafd$0$174
struct S
{
int arr[5];
}; 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++?


Yes, the assignment copies the array contents, in both C and C++. Same
thing for the copy constructor.
Jul 22 '05 #2

P: n/a
David Rasmussen wrote:
If I have this

struct S
{
int arr[5];
};

and I do this:

S s1,s2;

...

s1 = s2;

what happens?
The entire object gets copied. The array is a subobject of that object,
which means that it gets copied too.
Normally, array assignments aren't possible/allowed. If I do s1.arr =
s2.arr I get a compiler error.
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.
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++.
What pointer? There's no "pointer to the start of the array" in this
example.
Is there any difference in semantics here betweeen C and C++?


No.

--
Best regards,
Andrey Tarasevich

Jul 22 '05 #3

P: n/a
Andrey Tarasevich wrote:
Normally, array assignments aren't possible/allowed. If I do s1.arr =
s2.arr I get a compiler error.


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.


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
Jul 22 '05 #4

P: n/a
Siemel Naran wrote:

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


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

/David
Jul 22 '05 #5

P: n/a
David Rasmussen wrote:

Siemel Naran wrote:

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


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


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
kb******@gascad.at
Jul 22 '05 #6

P: n/a

"David Rasmussen" <da*************@gmx.net> wrote in message
news:40*********************@dtext02.news.tele.dk. ..
Siemel Naran wrote:

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


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


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
Jul 22 '05 #7

P: n/a
John Harrison wrote:

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.


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
Jul 22 '05 #8

P: n/a

"David Rasmussen" <da*************@gmx.net> wrote in message
news:40*********************@dtext02.news.tele.dk. ..
John Harrison wrote:

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.


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


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
Jul 22 '05 #9

P: n/a
David Rasmussen posted:
Normally, array assignments aren't possible/allowed. If I do s1.arr =
s2.arr I get a compiler error.

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!

If I do s1 = s2 it compiles fine.

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(const 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(NameBuffer, pNameToRegister);

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

struct StringCopierStructureBuffer
{
char NameBuffer[30];
};

StringCopierStructureBuffer* pInput = (StringCopierStructureBuffer*)
pNameToRegister;

StringCopierStructureBuffer 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
Jul 22 '05 #10

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


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

Jul 22 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.