В частности, может ли он указывать на int/float и т.д.? Как насчет таких объектов, как NSString и т.п.? Будем очень благодарны за любые примеры.
Что такое void * и какие переменные/объекты он может указывать на
Ответ 1
void*
- такой указатель, что любой указатель может быть неявно преобразован в void*
.
Например:
int* p = new int;
void* pv = p; //OK;
p = pv; //Error, the opposite conversion must be explicit in C++ (in C this is OK too)
Также обратите внимание, что указатели на const не могут быть преобразованы в void*
без const_cast
например.
const int * pc = new const int(4);
void * pv = pc; //Error
const void* pcv = pc; //OK
Hth.
Ответ 2
В C любой указатель может указывать на любой адрес в памяти, поскольку информация типа находится в указателе, а не в целевом. Таким образом, int * - это просто указатель на некоторое расположение памяти, которое считается целочисленным. Указатель void * - это просто указатель на ячейку памяти, где тип не определен (может быть что угодно).
Таким образом, любой указатель может быть отброшен в void *, но не наоборот, потому что кастинг (например) указатель на указатель на int указывает на его добавление - путем выполнения акта вы объявляете, что цель данные целые, поэтому, естественно, вы должны прямо сказать это. Другое дело, все, что вы делаете, говорит, что указатель int - это какой-то указатель, и это нормально.
Это, вероятно, то же самое в С++.
Ответ 3
A void *
может указывать на любую подобную данным вещь в памяти, такую как целочисленное значение, структуру или что-то еще.
Обратите внимание, однако, что вы не можете свободно конвертировать между void *
и указателями функций. Это связано с тем, что на некоторых архитектурах код не находится в том же адресном пространстве, что и данные, и, следовательно, возможно, что адрес 0x00000000 для кода относится к другому набору бит, чем адрес 0x00000000 для данных.
Было бы возможно реализовать компилятор, чтобы void *
был достаточно большим, чтобы запомнить разницу, но в целом я думаю, что это не сделано, вместо этого язык оставляет его undefined.
На типичных/основных компьютерах код и данные находятся в одном и том же адресном пространстве, а затем компиляторы обычно генерируют разумные результаты, если вы храните указатель на функцию void *
, так как это может быть весьма полезно.
Ответ 4
Помимо всего остального, что уже было сказано другими пользователями, void*
он обычно используется в определениях обратного вызова. Это позволяет вашему обратному сообщению получать пользовательские данные любого типа, включая ваши собственные определенные объекты/структуры, которые перед тем, как использовать его, должны быть добавлены к соответствующему типу:
void my_player_cb(int reason, void* data)
{
Player_t* player = (Player_t*)data;
if (reason == END_OF_FILE)
{
if (player->playing)
{
// execute stop(), release allocated resources and
// start() playing the next file on the list
}
}
}
Ответ 5
void*
может указывать на адрес в памяти, но синтаксис не имеет информации о типе. вы можете использовать его для любого типа указателя, но вы несете ответственность за то, чтобы этот тип соответствовал семантике данных.