Существует два возможных ответа на ваш вопрос, в зависимости от того, имеет ли компилятор ключ к данным, на которые он ссылается, или нет.
Объявление указателя типа int *
, char *
или mytype *
указывает компилятору, что более поздняя попытка разыменования его с помощью унарного оператора *
должна привести к результату int
, char
или mytype
соответственно.
В другом случае вы обычно сохраняете указатель либо в void *
(универсальный, нетипизированный указатель), либо в uintptr_t
(беззнаковое целое с таким же размером указателя, но без семантики указателя). В таком случае компилятор не знает, как интерпретировать оператор разыменования, поэтому вы должны явно привести такой указатель к другому типу указателя, и только затем разыменовать его:
int x = 5;
void *p = &x; /* p now points to an int, but the compiler doesn't know it */
printf("%d\n", *((int *) p)); /* we know what we did and don't rely on the compiler */
printf("%d\n", *p); /* compile-time error, dereferencing has undefined semantics */
Обратите внимание, что в скомпилированных неуправляемых языках, таких как C, отсутствует информация времени выполнения о том, на какие данные указывает указатель, в отличие от языков, таких как Java, где вы можете использовать оператор instanceof
, чтобы проверить, на что действительно указывает ссылка во время выполнения.