В чем разница между void* и void**?
Это специальное свойство, которому void* также может быть назначен указатель на указатель и отброшен назад, а исходное значение получено.
Я где-то читал эту строку. Значит ли это void*
и void**
такие же?
В чем разница?
редактировать
void*
может содержать любой указатель. Тогда что такое void**
нужны?
6 ответов
один указывает на черную дыру.
другой указывает на вещь, указывающую на черную дыру.
они на самом деле не одно и то же, но указатели могут быть преобразованы в void *
. Вы можете конвертировать int *
до void *
потому что, ну, это указатель. void **
is еще указатель (он просто указывает на указатель), и так как это указатель, вы можете преобразовать его в void *
. В этом есть смысл?
тем не менее, я не думаю Я когда-либо использовал void **
, но если вам нужен массив void *
s, тогда тип будет void **
. (In C)void *
часто используется для удержания указателя на некоторые пользовательские данные, но вы не будете знать заранее, какой тип этих данных будет. Если у вас был массив из них, то void **
.
так как у вас также есть это помечено как C++: предыдущий случай на самом деле не применяется: вы можете использовать std::vector<void *>
. Действительно,void *
может быть сомнительным-абстрактная база может соответствовать вашим целям лучше. void *
полезен в основном в C.
пустота* * - указатель на пустоту*. Void* может быть преобразован туда и обратно в любой тип указателя (включая void**). Так что вы можете сделать:
char* -> void*
void* -> void**
void** -> void*
void* -> char*
Вы можете не do:
char* -> void**
void** -> char*
таким образом, они не то же самое.
A void *
может содержать любой указатель. Так как нет фактических void
объекты, a void *
всегда является указателем на какой-либо другой тип.
A void **
является указателем на указатель на void или адрес void *
, т. е. адрес указателя на Void. Это реальный тип и не имеет никаких магических свойств.
но поскольку void *
может содержать любой указатель, он также может содержать, например,void **
.
void **f(int x) {
static void *y;
static int *iy;
y = &x;
iy = &x;
// return &iy; // not ok
return &y; // ok
}
Если вы хотите сохранить какой-то указатель или что-то еще, вы, вероятно, будете использовать void*.
однако, если вы хотите написать функцию, которая может инициализировать этот волшебный указатель, то вам нужно передать этот аргумент этой функции как void**
void fun1();
int fun2(int);
double fun3(long);
bool fun4(int, long, double);
int rand(void** pp)
{
switch(time()%4)
{
case 0: *pp = fun1; return 0;
case 1: *pp = fun2; return 1;
case 2: *pp = fun3; return 2;
case 3: *pp = fun4; return 3;
}
}
int main()
{
void* pointer;
int funId;
funId = rand(&pointer);
setCallback(pointer, funId);
}
одно из основных различий заключается в том, что правило, которое вы указываете жирным шрифтом, не применяется к void**.
void* - указатель (или указатель на начало массива неизвестного типа). void* - указатель на адрес указателя (или указатель на начало 2D-массива).
кроме того, если вы пишете на C (а не на C++), то нет параметра by-reference, только по значению или по указателю.
Э. Г.
// By value C and C++
void MyFunction(int a)
{
}
// By pointer C and C++
void MyFunction(int* a)
{
}
// By reference C++ only
void MyFunction(int& a)
{
}
Если вы хотите функцию, которая изменяет адрес указателя (например, void* ptr;)
и позволяет вызывающему коду by affected by перемена,
затем вам нужно передать указатель по ссылке pass ptr to (void*&) и использовать ptr внутри функции
или передайте указатель на указатель (void**) и передайте &ptr и используйте *ptr внутри функции.