tags:

views:

122

answers:

7

Suppose I have two int arrays x and y, and both of them have length 3. x={0,1,2}.

Is there any one step way to assign the values of x to y. When I do y=x, and try to print the values of y,

the code does not compile.

I dont want to go through the pain of writing a for loop, and write y[i]=x[i]

+3  A: 

You need to loop.

These are essentially fixed pointers, so you can't just assign one to another. You have to copy each value.

edit

Here's why I don't recommend memcpy:

  1. It's not faster for any small number of elements; it will likely be slower.

  2. The version of memcpy he's using does not include any safeguards to prevent buffer overrun. It's very easy, even for non-novices, to confuse the number of elements with the total size of the elements, leading to a serious bug. It's less easy to mess up a for loop.

  3. Since this is just C, you can (usually) safely memcpy an element. If this were C++, you would want to ensure that the copy constructor was invoked. This makes the use of memcpy a bad habit.

In direct response to Carl:

  1. Yes, memcpy can be very fast for large arrays of simple data. This is not what we're dealing with here, though.

  2. I'm not concerned about bugs in memcpy, but the ease of having a bug in using it. It requires the count of bytes, but the natural thing would be the count of elements. A for loop would use the element count. On many platforms, there are safer versions that infer the buffer size and prevent overwrites; I'd recommend one of those, if possible, when memcpy is a good idea.

  3. If this were an array of C++ objects, such as std::string, then using memcpy instead of invoking the copy constructor would be a bug in itself. Yes, I do realize that the example is C, not C++, but that doesn't make it a good idea.

Steven Sudit
Well a loop *will* have to happen, but you certainly don't need to do it yourself.
Carl Norum
You don't need to, but the compiler won't do it for you, and I would not recommend `memcpy` in this case.
Steven Sudit
Mind explaining why you don't recommend `memcpy` when it will do the job for him?
mathepic
Why would `memcpy` be slower? Not explained. Point 2 is irrelevent since the size of the arrays are known to be 3 ahead of time. Point 3 is irrelevent because its C, not C++, but you pointed that out so its okay.
mathepic
Regarding point #2, most people would just use `sizeof` on the array, which just does the Right Thing in this case. As for using `memcpy` to copy arrays, it's a fairly commonplace C idiom. C++ is a different language with different rules; just because something is frowned upon there doesn't mean it is equally applicable in C.
Pavel Minaev
@mathepic: For an array of three ints, the fastest copy would be to hardcode the whole thing: `a[0] = b[0]; a[1] = b[1]; a[2] = c[2]`. Having said that, a for loop would still be optimized very well. In contrast, `memcpy` is optimized for larger blocks of data, so the overhead could easily exceed the entire cost of the copy.
Steven Sudit
@Pavel: You do have a point, but I'm not sure I agree with your conclusion. First, like many people, all of the C code I've written in the last decade has technically been C++. Second, copying two buffers of the exact same size is the easiest case. The more general case would involve such things as copying the middle three out of five into a buffer of three. Using STL, that's easy to do quickly and safely. Using a for loop, it's easy to do quickly and safely. Using memcpy, it's a recipe for disaster. Essentially, it's a premature optimization.
Steven Sudit
If you're using C code thats compiling under C++, you are doing it wrong.
mathepic
Please let me know if you feel I've left any other issues unanswered or see any errors.
Steven Sudit
@mathepic: Then I must have been doing it wrong for some time now. I recently wrote a DLL that had to plug into the OS using a C-style interface. For security reasons, I was not able to take advantage of `std::string`, so I had to do C-style string manipulations. Nonetheless, I wrote it in a CPP file so that I could use the buffer-safe versions of `memcpy` and similar functions. If that's wrong, I don't *want* to be right.
Steven Sudit
You can do it with `count`: `memcpy(y, x, count * sizeof (x[0]));` but `count = sizeof(x) / sizeof(x[0])`. Note that `sizeof` tends to become a function instead of an operator.
levif
@Steven Sudit If you require C++, its not C code.
mathepic
@levif: Adding `count` to that doesn't improve anything.
Steven Sudit
@mathepic: The requirement was for C code, the best solution was to use C-like code in C++.
Steven Sudit
Several compilers can recognize `memcpy` calls with small constant length values and replace them with simple move instructions.
nategoose
@nategoose: This addresses only the issue of efficiency, and all it does is argue that `memcpy` *might not* be worse in some cases. But it's not going to be *better* for short arrays, regardless.
Steven Sudit
@Steven Sudit: count improves readiness.
levif
@levif: I'm sorry, but I don't understand. Readiness for what?
Steven Sudit
@Steven Sudit: `count` in my memcpy proposal has the same role than the upper bound of the copy loop. memcpy is scalable and can be inserted inline at the compiler will (unless forbidden by user). Moreover memcpy is the most efficient with unaligned data structure. A loop is falsely safer; bugs can be introduced anywhere in code ;)
levif
@levif: This doesn't explain what count improves readiness for, so I'm going to just disregard that statement. My point was that copying the middle few elements out of an array is trivial with a for loop but easy to get wrong with memcpy. I don't think that what you said in any way addresses this point. In fact, it appears to be unrefuted.
Steven Sudit
+12  A: 

You can use memcpy or memmove:

memcpy(y, x, sizeof x);
Carl Norum
You are correct that the loop inside `memcpy` will do the same job. This is not to suggest that the code you offer will run faster, much less that it will be safer.
Steven Sudit
On a lot of machines, `memcpy` is hugely optimized. Now, in this case, it's only a 3 element array, so that probably doesn't matter. Why would it not be safer? Somebody already debugged `memcpy` - if I write my own loop, I might make a mistake...
Carl Norum
@Carl: I've edited my answer with a full reply.
Steven Sudit
+3  A: 

Although you can't do this:

int x[ 3 ] = { 0, 1, 2 };  // an array of three items
int y[ 3 ];                // another array of three items

y = x;                     // compile error - y isn't a pointer that can be reassigned.

You can do this:

int x[ 3 ] = { 0, 1, 2 };
int *y = x;   // a pointer to an array

You're creating y as a pointer to the array x, rather than a copy of x. If you change the values of x, those changes will also appear when referencing y.

Bob Kaufman
Nice explanation.
Steven Sudit
A: 

You need to loop or to call a library function that does that for you, e.g. memcpy/memmove.

Matteo Italia
A: 

There is no way built into the language. You can probably find a library call to do it, though. If it's something you're doing frequently, you could easily write the function yourself.

StrixVaria
+1  A: 

If two or more variables are declared as the same type of struct, and the definition of the struct contains arrays, the variables can be assigned to each other and the arrays will be copied in their entirety. Sometimes it may be handy to create a struct containing a single array, for precisely that purpose.

supercat
That's true, but it's going to involve a reinterpret_cast and only works for specific sizes.
Steven Sudit
One can't assign between the array and the struct, but if one is always using a certain size of array for a certain purpose, using a "typedef" to define a struct type containing the array may be handy. On some embedded systems this may also improve code size; e.g. on PICC-18, a struct-to-struct copy will take seven words of code space; a "memcpy" will take twelve.
supercat
+1  A: 

Roll them up in a struct (or union, in this case).

struct int3 {
    int A[3];
};

int3 x = {{ 0, 1, 2 }};
int3 y = x;

This will not generally result in better code from the compiler than doing individual copies of each element or using memcpy, and may result in worse code.

nategoose