copy smaller array into bigger array?

M

Marcus

hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

i realize i can use a for loop, but just wondering how to do this with
other methods, perhaps memcpy (but how)?

unfortunately, my searches have turned up nothing for this type of
array copy, so any help would be greatly appreciated.

thanks,
marcus
 
S

Sjouke Burry

Marcus said:
hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

i realize i can use a for loop, but just wondering how to do this with
other methods, perhaps memcpy (but how)?

unfortunately, my searches have turned up nothing for this type of
array copy, so any help would be greatly appreciated.

thanks,
marcus
Learn Fortran. It has exactly what you want(and more).
 
I

Ian Collins

Marcus said:
hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

i realize i can use a for loop, but just wondering how to do this with
other methods, perhaps memcpy (but how)?

unfortunately, my searches have turned up nothing for this type of
array copy, so any help would be greatly appreciated.

You can't assign one array to another, but you can if you wrap one in a
class:

#include <tr1/array.hpp>

typedef std::tr1::array<int,10> Array;

int main()
{
Array foo;
std::tr1::array<Array,10> foo2;

foo2[0] = foo;
}
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

i realize i can use a for loop, but just wondering how to do this with
other methods, perhaps memcpy (but how)?

unfortunately, my searches have turned up nothing for this type of
array copy, so any help would be greatly appreciated.

Assuming it an array of PODs, you can use memcpy -- but it's only
rarely a really good idea.

For the specific case you mention, I'd probably use vectors instead:

std::vector<int> foo(10);

std::vector<std::vector<int> > foo2;
foo2.resize(10);

foo2[0] = foo;
// Or:
std::swap(foo, foo2[0]);

Using std::swap as above is different from using an assignment in (at
least) two ways. First of all, it'll usually be faster than an
assignment. Second, it'll turn foo into an empty vector -- foo[0] was
empty, and we're swapping the two, so now foo[0] is a vector of ten
ints, and foo is an empty vector (i.e. doesn't contain anything).
 
D

Default User

Marcus said:
hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

i realize i can use a for loop, but just wondering how to do this with
other methods, perhaps memcpy (but how)?

memcpy(foo2[0], foo, sizeof foo);



Brian
 
G

Gil

hi, given int foo[10] and int foo2[10][10], how would it be possible
to do something like foo2[0] = foo?

//following should do exactly what you want
std::copy( foo, foo + 10, foo2[ 0 ] );

gil
 
F

Fraser Ross

template <typename T, size_t N>
inline void copy(T (&lhs)[N], T (&rhs)[N]) {
std::copy_n(lhs, N, rhs);
}

copy(foo, foo2[0]);

Fraser.
 
F

Francesco

template <typename T, size_t N>
inline void copy(T (&lhs)[N], T (&rhs)[N]) {
 std::copy_n(lhs, N, rhs);
 }

copy(foo, foo2[0]);

Fraser.

Is copy_n really part of the STL?

I wasn't able to compile the code - copy_n doesn't appear in my
<algorithm> header - also, it is not present in TC++PL 3rd ed. nor
into the standard specs (but my copy of the standard dates back to
1996).

The following page:
http://www.cppreference.com/wiki/stl/algorithm/copy_n

States:
"copy_n
This function was part of the original SGI STL library, but never has
been a part of ISO C++."

Is it accurate and up to date?
 
F

Francesco

template <typename T, size_t N>
inline void copy(T (&lhs)[N], T (&rhs)[N]) {
std::copy_n(lhs, N, rhs);
}
copy(foo, foo2[0]);

Is copy_n really part of the STL?

I wasn't able to compile the code - copy_n doesn't appear in my
<algorithm> header - also, it is not present in TC++PL 3rd ed. nor
into the standard specs (but my copy of the standard dates back to
1996).

The following page:http://www.cppreference.com/wiki/stl/algorithm/copy_n

States:
"copy_n
This function was part of the original SGI STL library, but never has
been a part of ISO C++."

Is it accurate and up to date?

template <typename T, size_t N>
inline void copy(T (&lhs)[N], T (&rhs)[N]) {
std::copy_n(lhs, N, rhs);
}
copy(foo, foo2[0]);

Is copy_n really part of the STL?

I wasn't able to compile the code - copy_n doesn't appear in my
<algorithm> header - also, it is not present in TC++PL 3rd ed. nor
into the standard specs (but my copy of the standard dates back to
1996).

The following page:http://www.cppreference.com/wiki/stl/algorithm/copy_n

States:
"copy_n
This function was part of the original SGI STL library, but never has
been a part of ISO C++."

Is it accurate and up to date?

What do you thing about this version, which allows copying a smaller
array to the beginning of a larger one and uses std::copy which is
surely part of the ISO STL?

-------
template <typename T, size_t Nfrom, size_t Nto>
inline bool copy(T (&from)[Nfrom], T (&to)[Nto]) {
if (Nto < Nfrom) {
return false;
} else {
std::copy(from, &from[Nfrom], to);
return true;
}
}
 
F

Fraser Ross

"Francesco"
Its in the latest draft standard. Some libraries might have it within
the TR1 namespace.

Its out of date. Its quite well known that copy_if was omitted by the
standard.

What do you thing about this version, which allows copying a smaller
array to the beginning of a larger one and uses std::copy which is
surely part of the ISO STL?

-------
template <typename T, size_t Nfrom, size_t Nto>
inline bool copy(T (&from)[Nfrom], T (&to)[Nto]) {
if (Nto < Nfrom) {
return false;
} else {
std::copy(from, &from[Nfrom], to);
return true;
}
}

The OP has arrays of a single size. I don't think your function has any
use as it is. Nfrom and Nto are compile-time constants and you have a
run-time comparison of them. You have taken the address of a
non-existing element from[Nfrom] which is usually doable but isn't good.
You can write from + Nfrom.


Fraser.
 
F

Francesco

"Francesco"

Its in the latest draft standard. Some libraries might have it within
the TR1 namespace.

Its out of date. Its quite well known that copy_if was omitted by the
standard.
What do you thing about this version, which allows copying a smaller
array to the beginning of a larger one and uses std::copy which is
surely part of the ISO STL?
-------
template <typename T, size_t Nfrom, size_t Nto>
inline bool copy(T (&from)[Nfrom], T (&to)[Nto]) {
if (Nto < Nfrom) {
return false;
} else {
std::copy(from, &from[Nfrom], to);
return true;
}
}

The OP has arrays of a single size. I don't think your function has any
use as it is. Nfrom and Nto are compile-time constants and you have a
run-time comparison of them. You have taken the address of a
non-existing element from[Nfrom] which is usually doable but isn't good.
You can write from + Nfrom.

Fraser.
"Francesco"

Its in the latest draft standard. Some libraries might have it within
the TR1 namespace.

Thank you, I didn't knew that.
Its out of date. Its quite well known that copy_if was omitted by the
standard.
What do you thing about this version, which allows copying a smaller
array to the beginning of a larger one and uses std::copy which is
surely part of the ISO STL?
-------
template <typename T, size_t Nfrom, size_t Nto>
inline bool copy(T (&from)[Nfrom], T (&to)[Nto]) {
if (Nto < Nfrom) {
return false;
} else {
std::copy(from, &from[Nfrom], to);
return true;
}
}

The OP has arrays of a single size. I don't think your function has any
use as it is. Nfrom and Nto are compile-time constants and you have a
run-time comparison of them. You have taken the address of a
non-existing element from[Nfrom] which is usually doable but isn't good.
You can write from + Nfrom.

Fraser.

You're right, the different sized array assignment wasn't requested so
there is no need for my function in this particular case, although it
works just fine - that's just a more flexible version instead of a
more specialized one, as I see it.

Could you please explain me why it isn't good to use "&from[Nfrom]",
being that "from + Nfrom" is just exactly the same thing, and since
the standard allows me to take the address of the first element past
the array in either way? Am I mistaking the standard or is it just
matter of tastes?

About the runtime check, if I understand it right, a good compiler
should be able to optimize away that comparison and generate the
actual functions accordingly. On the other hand, if I omit that check,
my code could call that function with a bad couple of arrays and I
would end up writing outside the boundaries, instead of having a safe
do-nothing function which just returns false.

I've just tried the same function without that check, it just compiled
and it just wrote outside the boundaries as expected, when fed with
the wrong arrays. Is there a way to do such a check at compile time,
allowing the compiler to issue a warning or an error about it?

In any case, that's just matter of curiosity, I think I would never
manage actual data in arrays that way. Maybe it could be worth doing
in some low-level, hidden, optimized function, I don't know.

Please don't take my words in the wrong way, I'm not the kind of
person who likes to dive into polemics, I'm just willing to learn new
things, that's why I'm responding to your points that way.

Have good time,
Francesco
 
F

Fraser Ross

"Francesco"
Could you please explain me why it isn't good to use "&from[Nfrom]",
being that "from + Nfrom" is just exactly the same thing, and since
the standard allows me to take the address of the first element past
the array in either way? Am I mistaking the standard or is it just
matter of tastes?

The former takes the address of a nonexisting element. The latter only
uses pointer arithmetic.

the wrong arrays. Is there a way to do such a check at compile time,
allowing the compiler to issue a warning or an error about it?

Yes theres static_assert in the latest draft standard. Heres a method
using the current standard:

namespace GlobalTypes {
template < bool >
struct CompileTimeChecker {
CompileTimeChecker(...) {}
};
template <>
struct CompileTimeChecker<false> {
};
}

#define STATIC_CHECK(expr, msg) \
{ \
class ERROR_##msg {}; \
(void)sizeof(( ::GlobalTypes::CompileTimeChecker<0 !=
(expr)>(ERROR_##msg()) )); \
}

You would write something like:
STATIC_CHECK(Nto >= Nfrom, DestinationTooShort)

Fraser.
 
M

MCD

thanks very much for all the replies! they've been very helpful and i
learned much more than i thought i would. am trying them out and
seeing which one works best.

regards
marcus
 
J

James Kanze

"Francesco"
Its in the latest draft standard. Some libraries might have
it within the TR1 namespace.
Its out of date. Its quite well known that copy_if was
omitted by the standard.

And copy_n, apparently. But it has since been reinstated.
What do you thing about this version, which allows copying a
smaller array to the beginning of a larger one and uses
std::copy which is surely part of the ISO STL?
-------
template <typename T, size_t Nfrom, size_t Nto>
inline bool copy(T (&from)[Nfrom], T (&to)[Nto]) {
if (Nto < Nfrom) {
return false;
} else {
std::copy(from, &from[Nfrom], to);

The second argument contains undefined behavior. Use from +
Nfrom instead.
The OP has arrays of a single size. I don't think your
function has any use as it is.

It's certainly useful for the case the original poster
presented--copying a one dimensional array into a row of a two
dimensional array. For his case, in fact, something like:

assert( Nto == Nfrom ) ;
std::copy( from, from + nFrom, to ) ;

would be even more appropriate.
Nfrom and Nto are compile-time constants and you have a
run-time comparison of them.

Agreed. Some form of static assert would be more appropriate.
You have taken the address of a non-existing element
from[Nfrom] which is usually doable but isn't good. You can
write from + Nfrom.

It's a good habit to get into. Taking the address of one past
the end of a C style array will usually work, even if it is
formally undefined behavior. Taking the address of one past the
end of any other container in this manner, however, will
normally cause the program to crash, at least with a good
implementation of the library.
 
J

James Kanze

"Francesco"
Could you please explain me why it isn't good to use
"&from[Nfrom]", being that "from + Nfrom" is just exactly
the same thing, and since the standard allows me to take the
address of the first element past the array in either way?
Am I mistaking the standard or is it just matter of tastes?
The former takes the address of a nonexisting element. The
latter only uses pointer arithmetic.

The former dereferences a pointer to a nonexisting element.
&from[Nfrom] is, by definition, &(*(from + Nfrom)). And that *
operator in there results in undefined behavior.

In practice, of course, every compiler will optimize &*... to a
no-op, and you'll get exactly the same code for both. But only
when the built-in operators are involved. If you invoke
&v[v.size()], you get the equivalent of &v.operator[]( v.size() ).
And in a good implementation of the library, v.operator[] will
cause a fatal error in the program when passed v.size(). So
it's a good habit to get into using first+size to get a pointer
to one past the end, rather than &first[size].
 
F

Fraser Ross

"James Kanze"
It's certainly useful for the case the original poster
presented--copying a one dimensional array into a row of a two
dimensional array. For his case, in fact, something like:
assert( Nto == Nfrom ) ;
std::copy( from, from + nFrom, to ) ;
would be even more appropriate.

The function I wrote also does that. His allows target arrays of
different lengths. STL has overloaded swap for like sized arrays and I
wonder why it wasn't done for copy, copy_if, copy_backward, and possible
move and move_backward.

I'm not sure what move does. Can it be implemented with a 2003 standard
compiler? Are constructors and destructors invoked? What fills the
location moved from?

Fraser.
 
F

Francesco

"Francesco"
Could you please explain me why it isn't good to use "&from[Nfrom]",
being that "from + Nfrom" is just exactly the same thing, and since
the standard allows me to take the address of the first element past
the array in either way? Am I mistaking the standard or is it just
matter of tastes?

The former takes the address of a nonexisting element.  The latter only
uses pointer arithmetic.

Well, I'd have expected some kind of argumentation instead of an
explanation which is pretty obvious - I understand that my "hobbyist"
label doesn't give any pointer about the level of my knowledge, hence
this explanation of yours _could have been_ not obvious for me.

Let's put a point: I'll buy pointer arithmetic just for the sake of
the fewer keystrokes.

For everything else, since "&from[Nfrom]" and "from + Nfrom" represent
exactly the same address, I still see it as matter of tastes. James
Kanze raised another issue about it but I'll respond to that by
replying to his post.
Yes theres static_assert in the latest draft standard.  Heres a method
using the current standard:

namespace GlobalTypes {
template < bool >
struct CompileTimeChecker {
 CompileTimeChecker(...) {}
 };
template <>
struct CompileTimeChecker<false> {
 };

}

#define STATIC_CHECK(expr, msg) \
{ \
class ERROR_##msg {}; \
(void)sizeof(( ::GlobalTypes::CompileTimeChecker<0 !=
(expr)>(ERROR_##msg()) )); \

}

You would write something like:
STATIC_CHECK(Nto >= Nfrom, DestinationTooShort)

Thank you, this method will eventually come handy before the
implementation of static_assert (which of course I wasn't aware of).

All the best,
Francesco
 
F

Francesco

thanks very much for all the replies! they've been very helpful and i
learned much more than i thought i would. am trying them out and
seeing which one works best.

regards
marcus

You're welcome. It's nice to see the OP feedback from time to time ;-)

(of course the sentence above is meant in general, not for you in
particular)

All the best,
Francesco
 
F

Francesco

"Francesco"
Could you please explain me why it isn't good to use
"&from[Nfrom]", being that "from + Nfrom" is just exactly
the same thing, and since the standard allows me to take the
address of the first element past the array in either way?
Am I mistaking the standard or is it just matter of tastes?
The former takes the address of a nonexisting element. The
latter only uses pointer arithmetic.

The former dereferences a pointer to a nonexisting element.
&from[Nfrom] is, by definition, &(*(from + Nfrom)). And that *
operator in there results in undefined behavior.

I don't agree here. As I understand it, it is the act of _accessing_
the first element past the array to be undefined behavior, not the act
of composing, getting or passing its address in any manner.

Stroustrup does this in his example code...
int v[] = { 1, 2, 3, 4};
int* p3 = &v[4];
....and I wasn't able to find any clause of the standard giving a
different behavior or different requisites of behavior to the process
of creating an address using unary *, unary & and the subscript
operator.

On the contrary, I was able to understand that those operators are
expected _not to access_ the relative item(s) while creating the
address.
In practice, of course, every compiler will optimize &*... to a
no-op, and you'll get exactly the same code for both. But only
when the built-in operators are involved. If you invoke
&v[v.size()], you get the equivalent of &v.operator[]( v.size() ).
And in a good implementation of the library, v.operator[] will
cause a fatal error in the program when passed v.size(). So
it's a good habit to get into using first+size to get a pointer
to one past the end, rather than &first[size].

I'll definitely use pointer arithmetic in any case, both with the
built-in types where it seems to make no difference and with all the
other types that can be messed up, for the sake of surety - and for
the sake of the fewer keystrokes ;-)

Best regards,
Francesco
 

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

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top