В чем разница между void * и void **? - PullRequest
10 голосов
/ 12 июня 2010

Это специальное свойство, которому void * также можно присвоить указатель на указатель и привести обратно к исходному значению.

Я где-то читал эту строку. Значит ли это, что void* и void** одинаковы? В чем разница?

1009 ** * Редактировать 1010 ** * 1011

void* может содержать любой указатель. Тогда зачем нужен void**

Ответы [ 6 ]

53 голосов
/ 12 июня 2010

Одна указывает на черную дыру.

Другие указывают на вещь, указывающую на черную дыру.


Они на самом деле не одно и то же, но указатели могут бытьпреобразуется в void *.Вы можете конвертировать int * в void *, потому что это указатель.void ** является все еще указателем (он просто указывает на указатель), и, поскольку он является указателем, вы можете преобразовать его в void *.Это имеет какой-то смысл?

Тем не менее, я не думаю, что я когда-либо использовал void **, но если вам нужен массив void * s, тогда тип будет void **.(В C) void * часто используется для хранения указателя на некоторые пользовательские данные - но вы не будете знать заранее, какого типа будут эти данные.Если у вас есть их массив, то void **.

Поскольку вы также пометили это как C ++: предыдущий случай на самом деле не применим: вы можете использовать std::vector<void *>.Действительно, void * может быть сомнительным - абстрактная база может лучше соответствовать вашим целям.void * полезен в основном на C.

6 голосов
/ 12 июня 2010

Пустота ** - указатель на пустоту *.Void * может быть преобразован назад и вперед в любой тип указателя (включая void **).Так что вы можете сделать:

char* -> void*
void* -> void**
void** -> void*
void* -> char*

Вы можете не сделать:

char* -> void**
void** -> char*

, чтобы они не совпадали.

3 голосов
/ 12 июня 2010

A void * может содержать любой указатель. Поскольку реальных void объектов не существует, 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
}
2 голосов
/ 12 июня 2010

если вы хотите сохранить какой-либо указатель или что-то еще, вы, вероятно, будете использовать 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);
}
1 голос
/ 12 июня 2010

Одно существенное отличие состоит в том, что правило, которое вы цитируете жирным шрифтом, не применяется к void **.

0 голосов
/ 12 июня 2010

void * - указатель (или указатель на начало массива неизвестного типа).void * - указатель на адрес указателя (или указатель на начало двумерного массива).

Кроме того, если вы пишете на C (а не на C ++), то нетпараметр -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;)
ивключает вызывающий код, на который повлияло изменение,
, затем вам нужно передать указатель с помощью ссылки ptr в (void * &) и использовать ptr внутри функции
или передать указатель на указатель (void **) и передайте & ptr и используйте * ptr внутри функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...