В чем разница между 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 внутри функции.