За C 2018 6.5.16.1 1, когда левый операнд имеет тип void *
, правый операнд может иметь тип int *
:
Один из следующих должен содержать ... левый операнд имеет атоми c, квалифицированный или неквалифицированный тип указателя, и (учитывая тип, который левый операнд будет иметь после преобразования в lvalue) один операнд является указателем на тип объекта, а другой - указателем на квалифицированный или неквалифицированный версия void, а тип, на который указывает левый, имеет все квалификаторы типа, на который указывает правый…
Согласно 6.5.16.1 2, тогда правый операнд автоматически преобразуется в тип левый операнд:
… значение правого операнда преобразуется в тип выражения присваивания…
Таким образом, в (int *)&a
значение &a
, имеющий тип int *
, преобразуется приведением в int *
, что не имеет никакого эффекта. Затем для назначения оно автоматически преобразуется в void *
, а результат сохраняется в ptr
.
Тип ptr
остается void *
, как он объявлен. C не будет автоматически отслеживать, что значение в ptr
происходит от int *
.