Я работаю над старой базой кода и почти каждый вызов free () использует приведение своего аргумента. Например,
free((float *)velocity);
free((float *)acceleration);
free((char *)label);
где каждый указатель имеет соответствующий (и соответствующий) тип. Я не вижу смысла делать это вообще. Это очень старый код, поэтому мне остается только подумать, что это за K & R. Если это так, я действительно хочу поддерживать старые компиляторы, которые, возможно, требовали этого, поэтому я не хочу их удалять.
Есть ли техническая причина использовать эти приведения? Я даже не вижу прагматичной причины использовать их. Какой смысл напоминать себе о типе данных прямо перед его освобождением?
РЕДАКТИРОВАТЬ: Этот вопрос не является дубликатом другого вопроса. Другой вопрос является частным случаем этого вопроса, который, я думаю, очевиден, если близкие избиратели прочитают все ответы.
Колофон: Я ставлю галочку "const answer", потому что это реальная причина, почему это может быть необходимо сделать; тем не менее, ответ о том, что это был пре-ANSI C обычай (по крайней мере, среди некоторых программистов), кажется, является причиной его использования в моем случае. Много хороших моментов многими людьми здесь. Спасибо за ваш вклад.
void*
предстандартного C, а толькоchar*
. Поэтому, если ваши археологические находки выявили код, приводящий параметр к free (), я считаю, что он должен быть либо из этого периода, либо написан существом того времени. Хотя я не могу найти источник для этого, поэтому я воздержусь от ответа.Ответы:
Приведение может потребоваться для разрешения предупреждений компилятора, если указатели есть
const
. Вот пример кода, который вызывает предупреждение без приведения аргумента free:И компилятор (gcc 4.8.3) говорит:
Если вы используете
free((float*) velocity);
компилятор, перестает жаловаться.источник
float*
перед освобождением. Я пробовалfree((void *)velocity);
с gcc 4.8.3. Конечно, это не сработает с древним компиляторомconst char *p
качестве аргумента , а затем освобождает его, правильная вещь , чтобы сделать , это не актерский ,p
чтобыchar*
перед вызовом бесплатно. Воconst char *p
-первых, это не означает, что он*p
должен быть принят , поскольку он изменяется и должен быть объявлен соответствующим образом. (И если вместо указателя на const требуется указатель const,int *const p
вам не нужно приводить, так как он на самом деле допустим и, следовательно, отлично работает без приведений.)У предстандарта C не было ничего,
void*
кромеchar*
, так что вы должны были привести все переданные параметры Если вы столкнетесь с древним кодом C, вы можете найти такие приведения.Подобный вопрос со ссылками .
Когда первый стандарт C был выпущен, прототипы таНос и бесплатно изменилось от того ,
char*
наvoid*
что у них еще есть сегодня.И, конечно, в стандарте C такие броски излишни и просто вредят читабельности.
источник
free
приводите аргумент к тому же типу, который уже есть?free
работать в стандартном C (вам не нужно приводить). Я не читал 1-е издание, поэтому не могу сказать, были ли они запутаны и в нестандартные времена 80-х годов.void*
, но у него также не было прототипов функций, поэтому приведение аргумента по-free
прежнему было ненужным даже в K & R (при условии, что все типы указателей данных использовали одно и то же представление).char *
. Какой смысл в старых компиляторахvoid
? Чего добились бы такие броски?Вот пример, где free потерпит неудачу без приведения:
В C вы можете получить предупреждение (есть в VS2012). В C ++ вы получите ошибку.
За исключением редких случаев, кастинг просто раздувает код ...
Изменить: я бросил, чтобы
void*
неint*
показывать сбой. Он будет работать так же, какint*
будет преобразован вvoid*
неявно. Добавленint*
код.источник
void *
, а кfloat *
иchar *
. Эти броски не просто посторонние, они ошибаются.free(p)
потерпит неудачу? Это даст ошибку компилятора?const
указателями квалификаторов, очевидно.volatile
существует с тех пор, как C был стандартизирован, если не дольше. Это не было добавлено в C99.Старая причина: 1. При использовании в
free((sometype*) ptr)
коде явно указывается тип, указатель должен рассматриваться как частьfree()
вызова. Явное приведение полезно, когдаfree()
его заменяют на (сделай сам)DIY_free()
.DIY_free()
Был (есть) способ, особенно в режиме отладки, чтобы сделать во время выполнения анализа указателя освобождения. Это часто сочетается сDIY_malloc()
добавлением предложений, подсчета общего использования памяти и т. Д. Моя группа использовала эту технику в течение многих лет, прежде чем появились более современные инструменты. Он обязал, чтобы предмет, являющийся свободным, был приведен к типу, который был первоначально выделен.Современный: избегать
const
иvolatile
предупреждать в соответствии с указаниями Manos Nikolaidis @ и @egur . Думал , что я хотел бы отметить эффекты 3 классификаторов :const
,volatile
, иrestrict
.[править] Добавлено
char * restrict *rp2
за @R .. комментарийисточник
restrict
это не проблема, потому что он расположен - он влияет на объект, аrp
не на указатель типа. Если бы вы имелиchar *restrict *rp
, то это было бы важно.Вот еще одна альтернативная гипотеза.
Нам говорят, что программа была написана до C89, что означает, что она не может обойти какое-то несоответствие с прототипом
free
, потому что не только не было такой вещи, какconst
иvoid *
до C89, не было такой вещи, как прототип функции до C89.stdlib.h
Сам был выдумкой комитета. Если бы системные заголовки не удосужились объявитьfree
вообще, они бы сделали это так:Ключевым моментом здесь является то, что отсутствие прототипов функций означало, что компилятор не проверял тип аргумента . Он применил продвижение аргументов по умолчанию (те же, которые все еще применяются к вызовам функций с переменным числом аргументов), и это было именно так. Ответственность за то, чтобы аргументы в каждом месте вызова совпадали с ожиданиями вызываемого абонента, полностью ложится на программиста.
Тем не менее, это еще не означает, что необходимо было приводить аргументы в
free
большинстве компиляторов K & R. Функция какдолжен был быть правильно скомпилирован. Поэтому я думаю, что у нас есть программа, написанная для работы с ошибочным компилятором для необычной среды: например, для среды, где
sizeof(float *) > sizeof(int)
компилятор не будет использовать соответствующее соглашение о вызовах для указателей, если вы их в точку вызова.Я не знаю ни о какой такой среде, но это не значит, что ее не было. Наиболее вероятные кандидаты, которые приходят на ум, - это урезанные «крошечные C» компиляторы для 8- и 16-битных микро в начале 1980-х. Я также не удивлюсь, узнав, что у ранних Crays были такие проблемы.
источник
free принимает в качестве параметра только неконстантные указатели. Так что в случае константных указателей требуется явное приведение к неконстантному указателю.
Невозможно освободить константные указатели в C
источник