Недопустимое lvalue в ошибке присваивания при попытке сделать указатель NULL
Автор вопроса: ChrisОтветов: 5
У меня есть указатель структурного типа, который я сделал. При запуске программы он начинается как NULL, а затем я использую malloc/realloc, поскольку мне нужно добавить/удалить эти структуры, и я просто собирался использовать свой указатель, чтобы указать на первую структуру и перемещаться по ней как по массиву.
Когда я malloc/realloc, я всегда делаю размер "массива"/области в памяти на единицу больше, чем нужно. Я делаю это, чтобы установить для "последнего индекса"/области в памяти значение NULL, чтобы я мог сказать что-то вроде while (указатель! = NULL).
Я получаю сообщение об ошибке: неверное lvalue в назначении, когда пытаюсь присвоить NULL последней позиции в массиве/области памяти со строками:
// Realloc remotelist by adding one to connrhosts
connrhosts++;
remotelist = realloc(remotelist, sizeof(rhost)*(connrhosts + 1));
(remotelist + connrhosts) = NULL;
Я думаю, что я говорю:
Пришло время добавить новую структуру в мой массив, поэтому я увеличу число connrhosts на единицу.
Перераспределите память, указанную в remotelist, в новую область памяти размером с connrhosts (сколько структур я буду использовать), а также одно дополнительное пространство, чтобы я мог сделать его NULL
Укажите remotelist на новую область памяти
Используйте мой указатель remotelist и добавьте смещение connrhosts, которое теперь будет указывать на последний индекс области памяти и сделает этот указатель NULL.
Насколько я могу судить (или чувствовать), я все сделал правильно, но я уже некоторое время работаю над этим проектом и у меня сложилось впечатление, что у меня узкое зрение. Я бы хотел, чтобы свежий взгляд взглянул на мою логику/код и дал мне знать, что они думают и что я сделал неправильно. Спасибо еще раз. :D
Изменить. Часть моей проблемы заключается в том, что я неправильно понимаю, что я могу делать с указателями.
Вот моя структура:
typedef struct {
char address[128]; // Buffer that holds our address of the remote host
int port; // Port of the remote host
int conn; // FD to the connection of our remote host
int ofiles; // Open files associated with the remote host
} rhost;
Я надеялся, что смогу прокрутить свой массив/область памяти и сказать, что если это не NULL, то сделайте что-нибудь с ним. Итак, мой исходный оператор цикла - это while (NULL != remotelist). Теперь я считаю, что читаю ответы и комментарии о том, что эта логика неверна, потому что я проверяю, является ли указатель нулевым? Я должен проверить, является ли область памяти/структуры, на которую указывает указатель, нулевой? Если это так, то должно быть что-то вроде while (NULL != *(remotelist + someoffset))?
Я делаю это так, как мой учитель предложил/говорил об этом в классе.
Кстати, почему вы делаете ++connrhosts, а затем используете connrhosts + 1 в распределении? Какова цель этого дополнительного + 1? AnT 08.03.2010
connrhosts - это текущее количество удаленных хостов, к которым я тоже могу подключиться. Так что в моем массиве, если бы их было два и я не делал connrhosts + 1, у меня было бы только два индекса, 0 и 1, и оба указывали бы на структуру. Я делаю + 1, поэтому у меня может быть три индекса: 0, 1 и 2, где 0 и 1 указывают на структуру, а 2 может быть равно NULL. Таким образом, у меня могут быть такие операторы, как while (NULL != remotelist) Chris 08.03.2010
рост - это структура. Созданное вами выделение, на которое указывает remotelist, представляет собой массив этих структур, а не массив указателей. Вы не можете установить структуру в NULL, поэтому вам понадобится другой способ обозначить конец списка. Один из способов - сохранить целое число вместе со счетчиком и передать его вместе с указателем. Другой способ - использовать одно из полей rhost в качестве маркера конца данных, например сказать, что если ofiles равно -1, это означает конец массива. Вы можете использовать фактический массив указателей с нулевым завершением. Я не рекомендую это. Steve Jessop 08.03.2010
Что, если я скажу что-то вроде rhost **remotelist; Затем remotelist = realloc(remotelist, sizeof(*rhost)*(connrhosts + 1)); Смогу ли я тогда установить эти указатели в NULL? Chris 08.03.2010
Вы бы это сделали, но все, что вы получите, это массив указателей. Затем вы можете выделить несколько объектов rhost отдельно. Это sizeof(rhost*), или sizeof(*remotelist), а не sizeof(*rhost). Steve Jessop 08.03.2010
Ошибочные присваивания lvalue возникают, когда LHS является оцениваемым выражением, которое не становится переменной, которую можно присвоить. То, что вы делаете, выглядит как операция (арифметика указателя), которая должна быть на RHS.
Что вы можете сделать, это:
remotelist[connrhosts] = NULL; // array notation asuming
// remotelist is an array of pointers
предполагая, что connrhosts - это int или size_t, или вы можете сделать:
remotelist += connrhost; // pointer arithmetic
*remotelist = NULL; // assuming remotelist is an array of pointers.
Ответ 2 · рейтинг 3 · John Knoeller
Вам также необходимо разыменовать указатель.
*(remotelist + connrhosts) = NULL;
Хотя я думаю
remotelist[connrhosts] = NULL;
яснее.
Ответ 3 · рейтинг 2 · Jason Kresowaty
Вам нужно разыменовать указатель с помощью *, чтобы получить доступ к тому, что хранится в памяти, адресуемой указателем.
*(remotelist + connrhosts) = NULL;
Ответ 4 · DigitalRoss
Выражение pointer != NULL относится к самому указателю, а не к памяти, на которую ссылается указатель. Даже если вы можете присвоить ему значение NULL, это не решит проблему.
После увеличения указателя он не равен NULL, в нем есть адрес, адрес вашего последнего дополнительного слота структуры.
Я полагаю, вы могли бы установить эту область в 0 с помощью:
Затем вы можете сделать что-то вроде p->field == 0, если это поле никогда не равно 0 в реальной структуре...
Лично я бы справился с этой проблемой, если я правильно понял, либо выделением второго массива указателей на структуры, либо просто отслеживанием их количества, либо, что наиболее вероятно, использованием коллекции типа связанной список или дерево, то есть что-то с более изящными операциями раскрытия, чем realloc().
Ответ 5 · AnT
"Область памяти/структуры" нельзя присвоить NULL и нельзя сравнивать с NULL. NULL используется только с указателями.
Если вы хотите установить все поля [нововыделенной] структуры в нули, в C89/90 распространена идиома - сделать это с помощью инициализатора = { 0 }:
Или вы можете просто использовать memset (это хак).
Что касается проверки того, является ли запись в вашем массиве нулевой... Для этого нет встроенной операции, хотя функция memcmp может помочь
if (memcmp(&remotelist[i], &ZERO_HOST, sizeof ZERO_HOST) == 0)
/* All zeroes */;
(это тоже немного хак, хотя и менее "хакерский", чем memset).
но обычно так не делают. Да и смысла так делать нет. Как правило, вы должны просто выбрать только одно поле в своей структуре ("основное"), которое может сказать вам, используется ли структура: или нет, и сравнить только это единственное поле с 0
if (remotelist[i].address[0] == '\0')
/* Entry is not used */;