Что такое ** в C ++? - PullRequest
       45

Что такое ** в C ++?

36 голосов
/ 14 марта 2009

Я видел некоторый код, а также некоторые ошибки, сгенерированные из моего компилятора, которые имеют токен '**' перед переменной (например, ** имя переменной не указано - или что-то, я не могу вспомнить точно случайно) , Я вполне уверен, что это связано с указателями, если бы мне пришлось угадывать, похоже, что он пытается разыменовать дважды. «**» довольно не для Google. Может кто-нибудь указать мне хороший сайт / документацию или кто-нибудь захочет объяснить это здесь?

Спасибо.

Отличные отзывы. Если я могу добавить, в каких ситуациях полезно иметь указатель на указатель? Разве вы не должны просто использовать оригинальный указатель вместо создания еще одного указателя на исходный указатель?

Ответы [ 11 ]

44 голосов
/ 14 марта 2009

** на самом деле не только указатель на указатель (как в объявлении), но также разыменование разыменования (в выражении).

Он часто используется в C, в котором нет обозначения & для ссылок, например, обновить возвращаемое значение типа указателя:

int alloc_foo(struct foo **foo_ret)
{
    *foo_ret = malloc(sizeof(struct foo));
    return 1; /* to indicate success; return value in foo_ret */
}
30 голосов
/ 14 марта 2009

Вы можете распознать подпись для main ():

int main(int argc, char* argv[])

Следующее эквивалентно:

int main(int argc, char** argv)

В этом случае argv - это указатель на массив char *.

В Си оператор индекса [] - это просто еще один способ выполнения арифметики указателей. Например,

foo[i]

выдает тот же код, что и

*(foo + i)
11 голосов
/ 14 марта 2009

Это не ** токен. Это просто токен *, за которым следует другой токен *. В вашем случае у вас есть указатель на указатель, и его дважды разыменовывают, чтобы получить то, на что действительно указывают.

9 голосов
/ 14 марта 2009

** - указатель на указатель.

Это может быть матрица (массив массивов) или массив строк (массив char) и т. Д.

6 голосов
/ 14 марта 2009

Это двойное разыменование.

int i = 3;
int* ptr_to_i = &i;
int** ptr_to_ptr_to_i = &ptr_to_i;

std::cout << **ptr_to_ptr_to_i << std::endl;

Отпечатки 3.

5 голосов
/ 14 марта 2009

Я просто хотел подчеркнуть некоторые случаи использования указателя на указатель. Большинство из них затронуты другими постами, но я подумал, что повторение может помочь.

  • Позволяет вызываемому пользователю изменять указатель, принадлежащий вызывающему. Например, можно передать указатель на указатель на начало строки, а вызываемый объект может изменить указатель, на который указывает указатель, чтобы теперь указывать на позицию в строке, где встречается определенный символ.

  • Поскольку массивы уменьшаются до указателей (и указатели можно рассматривать как массивы), вы часто будете видеть указатель на указатель, если у вас есть:

    • Указатель на массив. Это обобщение вышеприведенного случая, так как «строка» (в любом случае строка в стиле C) - это просто массив char s.

    • Массив указателей. Например, у вас может быть массив указателей на объекты, допускающий полиморфизм, или массив указателей для выбора объектов, хранящихся в другой коллекции.

    • Массив массивов. Опять же, массивы уменьшаются до указателей, так что это частный случай выше. Это часто используется для так называемых «зубчатых» массивов (в отличие от прямоугольных).

4 голосов
/ 14 марта 2009

Вы можете интерпретировать это буквально - указатель на указатель

3 голосов
/ 14 марта 2009
  • int **var объявляет указатель на указатель
  • **var ссылается на содержимое указателя, который сам по себе указывает на указатель
1 голос
/ 14 марта 2009
1 голос
/ 14 марта 2009

Одним из распространенных применений является то, что функция позволяет установить указатель на ноль.
Таким образом, free (pointer) освобождает память, выделенную для указателя, но оставляет указатель опасно, указывая на свободную память.
Вместо этого объявите my_free (** указатель) и вызовите my_free (& pointer), чтобы my_free () могла установить указатель в null после освобождения.

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