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 * car; вместо char * car[MAXINT]; это компилирует прекрасный. но я не вижу, как это было бы полезно для меня позже, когда я должен получить доступ к определенной информации с помощью индекса, это было бы очень раздражающим для доступа к той информации позже. на самом деле я даже не уверен, иду ли я о правильном пути, возможно, существует лучший способ сохранить набор строк вместо того, чтобы использовать массив символа *?

Править: Я не означал использовать INT_MAX (максимальное значение интервала), просто некоторый другой интервал, - приблизительно 20.

6
задан Fantastic Fourier 5 April 2010 в 02:41
поделиться

4 ответа

Вы создаете новый массив размером MAXINT. Я думаю, вы хотите создать указатель на массив размером MAXINT.

Создание указателя на массив элементов char *:

Ниже приведен массив размером MAXINT для элементов char *:

char * car[MAXINT]; 

Ниже приведен указатель на: массив размера MAXINT для элементов char * :

char* (*car)[MAXINT];

следующим образом вы устанавливаете указатель на: массив размера MAXINT на элементы char *:

char* (*car)[MAXINT];
car = &arg->_car;

Другие синтаксические ошибки в вопросе:

  • Вам необходимо поставить точку с запятой после определения структуры.
  • Вы должны использовать foo * , а не foo . Так должно быть:
    struct foo * thing = (struct foo *) arg;
  • Вы должны использовать thing , а не arg :
    bar = thing- > _bar;
    car = thing -> _ car;
3
ответ дан 10 December 2019 в 00:36
поделиться

car и _car оба являются массивами, и вы не можете назначать массивы в C (кроме случаев, когда массив встроен в структуру (или объединение), и вы выполняете присваивание структуры).

Они также являются массивами указателей на char, а не указателями на массивы char. То, что вы написали в коде, вероятно, именно то, что вам нужно - вы можете хранить указатели до MAXINT имен в массиве. Однако вы должны правильно описать тип - как массив указателей на указатели char или char.

Указатель на массив символов будет выглядеть так:

char (*car)[MAXINT];

А точка на массив символьных указателей (спасибо, Брайан) будет выглядеть так:

char *(*car)[MAXINT];

Будьте осторожны с MAXINT; это может быть очень большой массив (в Linux определяет 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 * . Вы, вероятно, хотели использовать вещь в той или иной форме. Как заметил Брайан, здесь тоже есть проблемы:

Вы либо хотите:

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 * ' ).

5
ответ дан 10 December 2019 в 00:36
поделиться

Вы не можете назначить массив так, как вы это делаете. Можно делать поэлементное копирование.

for(int i = 0; i < MAXINT; i++)
{
  car[i] = (arg->_car)[i]
}

Обратите внимание: если строки не являются постоянными, вам может потребоваться использовать strcpy .

2
ответ дан 10 December 2019 в 00:36
поделиться

Нотация массивов в C закономерно сбивает с толку; ваш код не означает то, что вы думаете.

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

0
ответ дан 10 December 2019 в 00:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: