C Несовместимые типы в присвоении, проблема с указателями?

StackOverflow https://stackoverflow.com/questions/2576610

  •  24-09-2019
  •  | 
  •  

Вопрос

Привет, я работаю с 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. ПРИМЕЧАНИЕ: Вышеуказанное от верхней части моей головы и не скопирована из рабочей программы, поэтому я не могу обещать все * находятся в нужном месте. Я подозреваю, что это домашнее задание, поэтому я не хочу давать вам все...

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top