Я не думаю, что ты прав.Даже самые строгие из правил псевдонимов будут учитываться только тогда, когда память фактически выделена для определенной цели.Как только выделенный блок был возвращен обратно в кучу с free
, на него не должно быть никаких ссылок, и он может быть снова выдан malloc
.
И void*
, возвращаемым malloc
не подчиняется строгому правилу псевдонимов, поскольку стандарт прямо указывает, что указатель void может быть приведен к любому другому виду указателя (и обратно).Раздел 7.20.3 C99 гласит:
Указатель, возвращаемый в случае успешного выделения, соответствующим образом выравнивается, так что его можно назначить указателю на любой тип объекта и затем использовать для доступа к такому объекту илимассив таких объектов в выделенном пространстве (до тех пор, пока пространство не будет явно освобождено).
С точки зрения вашего обновления (пример), где вы не на самом делевернуть память обратно в кучу, я думаю, что ваша путаница возникает, потому что выделенный объект обрабатывается специально.Если вы ссылаетесь на 6.5/6
из C99, вы видите:
Эффективным типом объекта для доступа к его сохраненному значению является объявленный тип объекта, если таковой имеется (сноска 75: Выделенообъекты не имеют объявленного типа).
Перечитайте эту сноску, это важно.
Если значение сохраняется в объекте, у которого нет объявленного типа, через lvalue, имеющийтип, который не является символьным типом, тогда тип lvalue становится эффективным типом объекта для этого доступа и для последующих доступов, которые не изменяют сохраненное значение.
Если значение копируется вЕсли объект не имеет объявленного типа с использованием memcpy или memmove или копируется в виде массива символьного типа, то эффективный тип измененного объекта для этого доступа и для последующих обращений, которые не изменяют значение, является эффективным типом объекта, из которогозначение копируется, если оно есть.
Для всех других обращений к объекту, не имеющему объявленного типа, эффектive-тип объекта - это просто тип l-значения, используемого для доступа.
Другими словами, содержимое выделенного блока станет типом элемента данных, который вы используете.вставьте туда.
Если вы поместите туда float
, вы должны получить к нему доступ только как float
(или совместимый тип).Если вы введете int
, вы должны обрабатывать его только как int
(или совместимый тип).
Единственное, что вы не должны делать, это помещать определенныйтип переменной в эту память, а затем попытайтесь обработать ее как другой тип - одна из причин этого состоит в том, что объектам разрешено иметь представления ловушек (которые вызывают неопределенное поведение), и эти представления могут возникать из-за того, что один и тот же объект рассматривается как разные типы.
Итак, если вы должны хранить там int
до освобождения в вашем коде, а затем перераспределить его как указатель float
, вы должны не попытаться использоватьплавать, пока вы на самом деле не положите туда.До этого момента тип выделенного еще не float
.