Hi I'm working with C and I have a question about assigning pointers.
struct foo
{
int _bar;
char * _car[SOME_NUMBER]; // this is meant to be an array of char * so that it can hold pointers to names of cars
}
int foofunc (void * arg)
{
int bar;
char * car[SOME_NUMBER];
struct foo * thing = (struct foo *) arg;
bar = thing->_bar; // this works fine
car = thing->_car; // this gives compiler errors of incompatible types in assignment
}
car and _car have same declaration so why am I getting an error about incompatible types? My guess is that it has something to do with them being pointers (because they are pointers to arrays of char *, right?) but I don't see why that is a problem.
when i declared char * car;
instead of char * car[MAXINT];
it compiles fine. but I don't see how that would be useful to me later when I need to access certain info using index, it would be very annoying to access that info later. in fact, I'm not even sure if I am going about the right way, maybe there is a better way to store a bunch of strings instead of using array of char *?
EDIT: I didn't mean to use INT_MAX (maximum value of int), it's just some other int, which is about 20.
Array notation in C is legitimately confusing; your code doesn't mean what you think it means.
arg->_car
means "the address of the array_car
". Similarly,car
means "the address of the arraycar
". If you're trying to copy the contents of _car to car, then this will do it:But your real question, I think, is "what's the best way to store a list of strings?" This answer is: a dynamic list (one that grows automatically as you add items).
You'd declare it like this:
To add a car:
To list the cars:
To remove the car at position n:
This is completely routine in C. NOTE: The above is off the top of my head and not copied from a working program, so I can't promise all the * are in the right place. I suspect this is a homework assignment, so I don't want to give you everything...
You are creating a new array of size MAXINT. I think you want to create a pointer to an array of size MAXINT.
Creating a pointer to an array of char*'s:
The following is an array of size MAXINT to char* elements:
The following is a pointer to: an array of size MAXINT to char* elements:
the following is how you set a pointer to: an array of size MAXINT to char* elements:
Other syntax errors in the question:
foo*
notfoo
. So it should be:struct foo* thing = (struct foo *) arg;
thing
notarg
:bar = thing->_bar;
car = thing->_car;
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:
And a point to an array of character pointers (thanks, Brian) would look like:
Be careful of MAXINT; that could be a very large array (on Linux,
<values.h>
definesMAXINT
asINT_MAX
, which is at least 231-1).The code looks like:
Neither the assignment to bar nor car should compile at all -
arg
is avoid *
. You presumably meant to usething
in some shape or form. As Brian noted, there are problems there, too:You either want:
Or you want:
Or, indeed:
Finally, dealing with the array assignment, in C you can reasonably use
memmove()
to do this:The similar function
memcpy()
does not have reliable semantics if the areas to be copied overlap, whereasmemmove()
does; it is simpler to always usememmove()
because it always works correctly. In C++, you need to be cautious about usingmemmove()
(ormemcpy()
). 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 *
').You can't assign to an array the way you're doing. You can do an element-wise copy.
Note that if if the strings aren't constant, you may need to use
strcpy
.