car
and _car
are both arrays, and you cannot assign arrays in C (except when the array is embedded in a structure (or union) and you do a structure assignment).
They are also arrays of pointers to char, rather than pointers to arrays of char. What you have written in the code is probably what you want - you could store pointers to up to MAXINT names in the array. However, you should describe the type correctly - as an array of pointers to char or char pointers.
A pointer to an array of characters would look like:
char (*car)[MAXINT];
And a point to an array of character pointers (thanks, Brian) would look like:
char *(*car)[MAXINT];
Be careful of MAXINT; that could be a very large array (on Linux, <values.h>
defines MAXINT
as INT_MAX
, which is at least 231-1).
The code looks like:
struct foo
{
int _bar;
char * _car[MAXINT];
}
int foofunc (void * arg)
{
int bar;
char * car[MAXINT];
struct foo thing = (struct foo *) arg;
bar = arg->_bar; // this works fine
car = arg->_car; // this gives compiler errors of incompatible types in assignment
}
Neither the assignment to bar nor car should compile at all - arg
is a void *
. You presumably meant to use thing
in some shape or form. As Brian noted, there are problems there, too:
You either want:
int foofunc(void *arg)
{
int bar;
char *car[MAXINT];
struct foo thing = *(struct foo *)arg;
bar = thing._bar; // this works fine
car = thing._car; // this is still an array assignment
...other code using bar and car...
}
Or you want:
int foofunc(void *arg)
{
int bar;
char *car[MAXINT];
struct foo *thing = (struct foo *) arg;
bar = thing->_bar; // this works fine
car = thing->_car; // this is still an array assignment
...other code using bar and car...
}
Or, indeed:
int foofunc(void *arg)
{
struct foo *thing = (struct foo *) arg;
int bar = thing->_bar; // this works fine
char *car[MAXINT] = thing->_car; // this is still an array assignment
...other code using bar and car...
}
Finally, dealing with the array assignment, in C you can reasonably use memmove()
to do this:
int foofunc(void *arg)
{
struct foo *thing = (struct foo *) arg;
int bar = thing->_bar; // this works fine
char *car[MAXINT];
memmove(car, thing->_car, sizeof(car));
...other code using bar and car...
}
The similar function memcpy()
does not have reliable semantics if the areas to be copied overlap, whereas memmove()
does; it is simpler to always use memmove()
because it always works correctly. In C++, you need to be cautious about using memmove()
(or memcpy()
). In this code, it would be safe enough, but understanding why is non-trivial.
You do need to be aware that you are just copying pointers here - you are not copying the strings that the pointers point at. If something else changes those strings, it affects both the values seen via car
and the variable in the calling code.
One last point - for now: are you sure you need the argument to the function as a void *
? It opens up the code to all sorts of abuse which can be prevented if the function is declared to take a 'struct foo *
' instead (or even a 'const struct foo *
').