car
и _car
оба являются массивами, и вы не можете назначать массивы в C (кроме случаев, когда массив встроен в структуру (или объединение), и вы делаете присвоение структуры).
Они также являются массивами указателей на char, а не указателями на массивы char. То, что вы написали в коде, вероятно, то, что вы хотите - вы можете хранить указатели до максимум MAXINT имен в массиве. Тем не менее, вы должны правильно описать тип - как массив указателей на символ или указатель на символ.
Указатель на массив символов будет выглядеть так:
char (*car)[MAXINT];
И точка на массив символьных указателей (спасибо, Брайан) будет выглядеть так:
char *(*car)[MAXINT];
Будьте осторожны с MAXINT; это может быть очень большой массив (в Linux <values.h>
определяет MAXINT
как INT_MAX
, что по крайней мере 2 31 -1).
Код выглядит так:
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
}
Ни назначение bar, ни car не должны компилироваться вообще - arg
- это void *
. Вы, вероятно, хотели использовать thing
в той или иной форме. Как отметил Брайан, там тоже есть проблемы:
Вы либо хотите:
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...
}
Или вы хотите:
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...
}
Или, действительно:
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...
}
Наконец, имея дело с присваиванием массива, в C вы можете разумно использовать memmove()
для этого:
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...
}
Аналогичная функция memcpy()
не имеет надежной семантики, если копируемые области перекрываются, тогда как memmove()
имеет; проще всегда использовать memmove()
, потому что он всегда работает правильно. В C ++ вы должны быть осторожны с использованием memmove()
(или memcpy()
). В этом коде это было бы достаточно безопасно, но понимание почему нетривиально.
Вы должны знать, что вы просто копируете указатели здесь - вы не копируете строки, на которые указывают указатели. Если что-то еще изменяет эти строки, это влияет как на значения, видимые через car
, так и на переменную в вызывающем коде.
Еще один момент - пока: вы уверены, что вам нужен аргумент функции как void *
? Он открывает код для всех видов злоупотреблений, которые можно предотвратить, если объявить, что функция принимает вместо 'struct foo *
' (или даже 'const struct foo *
').