#c #variable-assignment #comma-operator #symmetry
#c #присвоение переменной #оператор запятой #симметрия
Вопрос:
Я пишу такой код:
#include <stdlib.h>
int main(void)
{
void *kilobyte;
kilobyte = malloc(1024);
kilobyte = NULL, free(kilobyte);
return 0;
}
для симметрии, что приятно. Но я никогда раньше не видел, чтобы кто-то еще использовал эту идиому, поэтому мне интересно, может ли это быть на самом деле непереносимым / небезопасным, несмотря на эту цитату из Википедии:
В языках программирования C и C оператор запятой (представленный токеном ,) является двоичным оператором, который вычисляет свой первый операнд и отбрасывает результат, а затем вычисляет второй операнд и возвращает это значение (и тип).
Редактировать: перепутал порядок. Теперь он компилируется gcc
без каких-либо предупреждений.
Комментарии:
1.
free
не возвращает значение, поэтому строка написана в плохом стиле. Код даже не менее типизирован, используйте стандартный ideom.2. AFAIK, оператор запятой отбрасывает
free
значение, которое естьvoid
, иNULL
вместо этого использует is . И меньше печатать, если ваш стиль требует последовательно присваивать указателям значение NULL после их освобождения.3. Нет значения для отбрасывания! Вы пытались скомпилировать это, прежде чем спрашивать? Вы нашли доказательство в стандарте, что это законно или незаконно? Пожалуйста, процитируйте раздел. (о, и я попробовал с gcc).
4. если вы попытаетесь скомпилировать его, это будет результатом
error: void value not ignored as it ought to be
5. Запустите свой «идеальный» код в отладчике!
Ответ №1:
Делая это:
kilobyte = NULL, free(kilobyte);
У вас утечка памяти.
Вы установили kilobyte
значение NULL, поэтому на какую бы память оно ни указывало, на нее больше нигде не ссылаются. Затем, когда вы это делаете free(kilobyte)
, вы эффективно выполняете free(NULL)
то, что не выполняет никаких операций.
Что касается free(NULL)
стандарта C.
7.22.3.3
free
Функция1.
#include <stdlib.h> void free(void *ptr);
2.
free
Функция
освобождает пространство, на которое указываетptr
, то есть делает его доступным для дальнейшего выделения. Еслиptr
это нулевой указатель, никаких действий не происходит. В противном случае, если аргумент
не соответствует указателю, ранее возвращенному
функцией управления памятью, или если пространство было освобождено
вызовомfree
илиrealloc
, поведение не определено.
Что касается вашего исходного кода перед редактированием:
kilobyte = free(kilobyte), NULL;
Проблема в том, что =
оператор имеет более высокий приоритет, чем ,
оператор, поэтому это утверждение эффективно:
(kilobyte = free(kilobyte)), NULL;
Это пытается установить переменную void
, значение которой не разрешено.
Вероятно, вы сделали отступ, чтобы сделать это:
kilobyte = (free(kilobyte), NULL);
Это освобождает указатель, а затем устанавливает указатель на NULL.
Как упоминалось Олафом в комментариях, вместо того, чтобы делать все в одной строке, было бы предпочтительнее сделать это вместо:
free(kilobyte);
kilobyte = NULL;
Выполнение этого более понятно для читателя, чем сведение кода к чему-то, что другие могут не понять, и (как вы теперь видели) менее подвержено ошибкам.