Из-за моего ограниченного рейтинга я пока не могу комментировать сообщения других, поэтому использование «ответа», пока это не ответ, а комментарий.
Ответ/комментарий Эрика Постпишила выше требует рецензирования. Я не согласен и не понимаю его рассуждений.
" ... Когда объект освобождается, несмотря на то, что байты в указателе не изменяются, данные в этих структурах могут измениться, и тогда попытка использовать указатель может потерпеть неудачу различными способами. В частности, попытка напечатать value может завершиться ошибкой, потому что .."
Обратите внимание на прототип стандартного вызова C free(): void free(void *ptr). В месте вызова ptr value останется неизменным до и после бесплатного вызова — он передается через value.
«Использовать» указатель будет/может потерпеть неудачу по-разному, если под использованием мы подразумеваем уважение к нему после вызова free(). Печать значения указателя не приводит к его уважению. Также печать (значения) указателя с вызовом printf с использованием %p должна быть корректной, даже если представление значения указателя определено реализацией.
"*... Однако, поскольку это правило существует, даже менее экзотические реализации C могут использовать его для оптимизации, поэтому компилятор C может реализовать free(x); printf("%p", (void *) x); эквивалентно free(x); printf("%p", (void ) NULL); например. ..."
Даже если он (компилятор) сделает это, я не могу легко понять, что бы это оптимизировало, вызов специального минимизированного printf со значением 0 для указателя? Также рассмотрите что-то вроде:
extern недействительным my_free (недействительным * ptr); // где-то определено.. my_free(myptr); printf("%p", myptr);
Ему нечего было бы оптимизировать, как вы здесь предлагаете, и он (компилятор) ничего не мог сделать о значении myptr.
Так что нет, я не могу согласиться с вашей интерпретацией стандарта C на данном этапе.
(мое) РЕДАКТИРОВАТЬ:
Если только в некоторых «экзотических» реализациях с указателем памяти, реализованным в виде структуры, и он передается в/из «пользовательского» void*. Тогда пользовательское значение кучи будет недействительным или нулевым при попытке его распечатать.. Но тогда каждый вызов C, который принимает void* в качестве указателя на память, должен будет различать, какой void* указывает на кучу, а не - скажем, memcpy, memset, - и тогда это становится довольно занятым...
person
v01d
schedule
20.06.2019