C Несовместимые типы в присвоении, проблема с указателями?
Вопрос
Привет, я работаю с C, и у меня есть вопрос о назначении указателей.
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 имеют ту же декларацию, поэтому почему я получаю ошибку о несовместимых типах? Я предполагаю, что у него есть что с ними делать указатели (потому что это указатели на массивы Char *, верно?) Но я не понимаю, почему это проблема.
Когда я заявил char * car;
вместо char * car[MAXINT];
Это компилируется нормально. Но я не вижу, как это было бы полезно для меня позже, когда мне нужно получить доступ к определенной информации, используя индекс, было бы очень раздражает доступ к этой информации позже. На самом деле, я даже не уверен, если я собираюсь пройти правильно, может быть, есть лучший способ хранить кучу строк, а не используя массив Char *?
Редактировать: Я не хотел использовать INT_MAX (максимальное значение int), это просто какой-то другой int, который составляет около 20.
Решение
Вы создаете новый массив размера Maxint. Я думаю, вы хотите создать указатель на массив размера Maxint.
Создание указателя на массив Char * 'S:
Ниже приведен массив размера Maxint для Char * Elements:
char * car[MAXINT];
Ниже приведен указатель: массив максимального размера для Char * элементов:
char* (*car)[MAXINT];
Ниже приведены то, как вы устанавливаете указатель на: массив максимального размера для Char * элементов:
char* (*car)[MAXINT];
car = &arg->_car;
Другие синтаксические ошибки в вопросе:
- Вы должны иметь запястье после определения вашей структуры.
- Вы должны использовать
foo*
нетfoo
. Отказ Так что это должно быть:
struct foo* thing = (struct foo *) arg;
- Вы должны использовать
thing
нетarg
:
bar = thing->_bar;
car = thing->_car;
Другие советы
car
а также _car
Оба массивы, и вы не можете назначать массивы в C (за исключением случаев, когда массив встроен в структуру (или соединение), и вы выполняете назначение структуры).
Они также являются массивами указателей, а не указателям на массивы CHAR. То, что вы написали в коде, вероятно, то, что вы хотите - вы могли бы хранить указатели на сумму до максимальных имен в массиве. Однако вы должны правильно описать тип - как массив указателей на указатели Char или Char.
Указатель на массив персонажей выглядел бы:
char (*car)[MAXINT];
И точка на массив указателей персонажей (спасибо, Брайан) будет выглядеть так:
char *(*car)[MAXINT];
Будьте осторожны с максиматом; это может быть очень большой массив (на Linux, <values.h>
определяет MAXINT
так как INT_MAX
, который не менее 231-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
}
Ни назначение баре, ни автомобилем, не должны компилировать вообще - 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 *
').
Вы не можете назначить массив, как вы делаете. Вы можете сделать элемент-мудрый экземпляр.
for(int i = 0; i < MAXINT; i++)
{
car[i] = (arg->_car)[i]
}
Обратите внимание, что если бы строки не будут постоянными, вам может потребоваться использовать strcpy
.
Обозначение массива в C является законно запутанным; Ваш код не означает, что вы думаете, что это значит.
arg->_car
означает «адрес массива _car
". По аналогии, car
означает «адрес массива car
«Если вы пытаетесь скопировать содержимое _Car на автомобиль, то это сделает это:
memcpy(car, _car, MAXINT);
Но твой реальный вопрос, я думаю, это «Какой лучший способ хранить список строк?» Этот ответ: динамический список (тот, который растет автоматически, как вы добавляете элементы).
Вы бы объявили это так:
#define CARSIZE 65
int numCars = 0;
char **car; /* a list of addresses, each one will point to a string */
Чтобы добавить машину:
char *newCar = malloc(CARSIZE); /* make room */
strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */
car[numCars++] = newCar; /* store it */
Чтобы перечислить автомобили:
int n;
for (n = 0; n < numCars; ++n)
printf("%s\n", car[n]);
Удалить автомобиль в положении n:
free(car[n]); /* release the memory */
/* condense the list of pointers */
for ( ; n < numCars - 1; ++n)
car[n] = car[n+1];
Это полностью рутина в C. ПРИМЕЧАНИЕ: Вышеуказанное от верхней части моей головы и не скопирована из рабочей программы, поэтому я не могу обещать все * находятся в нужном месте. Я подозреваю, что это домашнее задание, поэтому я не хочу давать вам все...