tags:

views:

167

answers:

5

Hi there,

It's been a long since I don't use C language, and this is driving me crazy. I have an array of structs, and I need to create a function which will copy one array to another (I need an exact copy), but I don't know how to define the function call. I guess I need to use pointers, but when I try it gives me an error.

struct group{
    int weight;
    int x_pos;
    int y_pos;
    int width;
    int height;
};

struct group a[4];
struct group b[4];

copySolution(&a, &b);

That last declaration send me an error. As I said, it's been a long since programming in C, so I'm a bit lost right now :(

+10  A: 

That should do it:

memcpy(&b, &a, sizeof(a));

EDIT: By the way: It will save a copy of a in b.

Johannes Weiß
Works like a charm. Thank you!
Víctor
good old trusty memcpy.
toto
You might add a " if(sizeof(b) >= sizeof(a)) ", check as well.
Fred
Fred, yeah, true! In real-world programs that should be done :-)
Johannes Weiß
Or more likely an assert, since there's usually nothing much a program can do to compensate for the programmer getting it wrong...
Steve Jessop
Use memmove() - it is guaranteed to be safe even for overlapping copies, unlike memcpy().
Jonathan Leffler
@onebyone: At least with a conditional you can attemp to fail gracefully as opposed to terminate the application.
Fred
@Jonathan: question says copying "one array to another". So they don't overlap. @Fred: "fail gracefully, or do not fail gracefully. There is no try". Some programmer thinks that array A fits inside array B, when it doesn't. Your program is in a state which you (the programmer of this routine) are certain is the result of a wrong assumption by a programmer. Under such dire circumstances, an assert *is* failing gracefully. Better to stop right now with a diagnostic, than to just keep executing broken code until eventually demons fly out of your nose.
Steve Jessop
... and of course you should consider yourself lucky if the assert actually does anything. If your caller is asking you to do something undefined now, there is every chance that this isn't the first time. The program could be doing anything. If you don't abort, there is every chance that it won't be the last. Just put the process down and back away slowly.
Steve Jessop
A: 

The compiler has no information about the size of the array after passing them as pointer into a function. So you often need a third parameter: The size of the arrays to copy.

A solution (without any error checking) could be:

void copySolution(struct group* a, struct group* b, size_t size) {
    memcpy(a, b, size * sizeof(*a));
}
dmeister
Not true. The original code passes the arrays as pointers of `struct group (*)[4]` type not as pointers `struct group *` type. With properly declared `copySolution` the array size is embedded in the pointer type. With your definition the original code simply won't compile, not only because of the missing third parameter, but also because the argument type doesn't match the parameter type.
AndreyT
I'm trying also that, since I need to pass the array to another function, and it says this:simulated_annealing.c: In function ‘main’:simulated_annealing.c:39: warning: passing argument 1 of ‘chooseNeighbour’ from incompatible pointer typeThe code:chooseNeighbour(}
Víctor
AndreyT
A: 

The easiest way is probably

 b=a

although a solution with memcpy() will also work.

Thomas
`b=a;` does not work when, as is the case here, `a` and `b` are arrays.
pmg
b=a simply copies the pointer value of a to b, which is not what OP wants
Ponting
`b=a` does not work -- arrays are not lvalues in C, so they cannot be assigned like this.
Adam Rosenfield
You could get a pointer to point at the same array with structs, but that is not a copy then.
Fred
@No Name: **get a name!** and that's wrong too. `b` cannot be assigned to since it's an array.
pmg
@Adam Rosenfield: Arrays are *lvalues* in C. Every object that has location in memory is called *lvalue* in C. Arrays are no exception. However, arrays in C are *non-modifiable* lvalues. This is why you can't assign to an array.
AndreyT
@pmg: you are right..
Ponting
A: 

This has a feel of poorly masqueraded homework assignment... Anyway, given the predetermined call format for copySolution in the original post, the proper definition of copySolution would look as follows

void copySolution(struct group (*a)[4], struct group (*b)[4])
{
  /* whatever */
}

Now, inside the copySolution you can copy the arrays in any way you prefer. Either use a cycle

void copySolution(struct group (*a)[4], struct group (*b)[4])
{
  const struct group *pb, *pbe;
  struct group *pa;

  for (pa = *a, pb = *b, pbe = pb + sizeof *b / sizeof **b; 
       pb != pbe; 
       ++pa, ++pb)
    *pa = *pb;
}

or use memcpy as suggested above

void copySolution(struct group (*a)[4], struct group (*b)[4])
{
  memcpy(b, a, sizeof *b);
}

Of course, you have to decide first which direction you want your arrays to be copied in. You provided no information, so everyone just jumped to some conclusion.

AndreyT
It's kind of homework, since it's my final project career :P truly, It's been a while and me an C could never get along each other :)
Víctor
A: 

As Johannes Weiß says, memcpy() is a good solution.

I just want to point out that you can copy structs like normal types:

for (i=0; i<4; i++) {
    b[i] = a[i]; /* copy the whole struct a[i] to b[i] */
}
pmg